<?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: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-15695660</id><updated>2011-12-20T01:47:24.091-07:00</updated><title type='text'>Tidbits @ Kassemi</title><subtitle type='html'>A collection of opinions, thoughts, tricks and misc. information.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>58</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-15695660.post-4957150261545784687</id><published>2006-11-15T23:10:00.000-07:00</published><updated>2006-11-15T23:12:55.846-07:00</updated><title type='text'>do away with pkg-config and combine your libraries</title><content type='html'>Short rant, but to hell with gnome for their libraries and dependencies. Just package glib, pango, atk, gtk, gtkmm, glibmm, and every other freaking pain in the ass library I need to install to get the gimp up and running in ONE thing!&lt;br /&gt;&lt;br /&gt;Pat from Slackware thought the same thing, and I'm sure the folks over at Freerock curse your name every time a new library comes out. ARGH!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-4957150261545784687?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/4957150261545784687/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=4957150261545784687' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/4957150261545784687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/4957150261545784687'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/11/do-away-with-pkg-config-and-combine.html' title='do away with pkg-config and combine your libraries'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-116218892426229778</id><published>2006-10-29T23:11:00.000-07:00</published><updated>2006-11-15T21:19:55.379-07:00</updated><title type='text'>Sample registration form</title><content type='html'>Heh. The &lt;a href="http://sourceforge.net/projects/kepty"&gt;framework's getting MUCH easier to use&lt;/a&gt;... And it's still not quite where I want it... Here's a quick little sample, a user registration process. This is the ENTIRE thing. Form validation, generation, database entry,&lt;br /&gt;etc. We've even got a great captcha generator that handles them fairly transparently.&lt;br /&gt;&lt;br /&gt;A focus on finishing up unit tests comes tomorrow after work... After that I'll be doing a separation between the server and framework, and then a few touchups and additions to the library and it's ready for the first alpha release... (it might be a while).&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;import kepty&lt;br /&gt;import datetime&lt;br /&gt;from kepty.lib.forms import *&lt;br /&gt;from kepty.lib.scaffolding import validate_input&lt;br /&gt;&lt;br /&gt;# Create a form...&lt;br /&gt;class RegisterForm(FormSkeleton):&lt;br /&gt;    username            = CharWidget(fv=Validator(min_length=2))&lt;br /&gt;    password            = PassWidget(fv=Validator(field_match='password_confirm'))&lt;br /&gt;    password_confirm    = PassWidget()&lt;br /&gt;    email               = CharWidget(fv=Validator(is_email=True))&lt;br /&gt;    birthdate           = DateTimeWidget(fv=Validator(max_age=18))&lt;br /&gt;    description         = TextWidget(fv=Validator(min_length=2))&lt;br /&gt;    captcha             = CaptchaWidget(fv=Validator(valid_captcha=True))&lt;br /&gt;&lt;br /&gt;# Creates a quick template file... We delete this command as soon as it's been run.&lt;br /&gt;&lt;br /&gt;RegisterForm().quick_start('/home/james/Projects/kepty/base/templates/tester/registration_form.tmpl')&lt;br /&gt;&lt;br /&gt;@validate_input(error='same')&lt;br /&gt;@kepty.expose(template='registration_form.tmpl')&lt;br /&gt;def register(request, errored=False, registration=RegisterForm):&lt;br /&gt;    if registration == None:&lt;br /&gt;        return dict(RegisterForm=RegisterForm())&lt;br /&gt;&lt;br /&gt;    if(errored):&lt;br /&gt;        return dict(RegisterForm=registration)&lt;br /&gt;&lt;br /&gt;    user = kepty.lib.database.ORM.create('users')&lt;br /&gt;    user.update(registration.all())&lt;br /&gt;    user.sync()&lt;br /&gt;&lt;br /&gt;    return "Thanks! You've been registered, %s!" % user.username&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;application = kepty.make_app(&lt;br /&gt;    (r'^/register$', register)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;kepty.mount('/tester', application, 'tester')&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-116218892426229778?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/116218892426229778/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=116218892426229778' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/116218892426229778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/116218892426229778'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/10/sample-registration-form.html' title='Sample registration form'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-116191907316000759</id><published>2006-10-26T19:50:00.000-07:00</published><updated>2006-11-15T21:19:55.294-07:00</updated><title type='text'>lighttpd, apache, boa, thttpd benchmarks - A quick server for Kepty</title><content type='html'>This past week I made the realization that I probably shouldn't be writing a small, quick and stable server from scratch for the &lt;a href="http://sourceforge.net/projects/kepty"&gt;Kepty Web Framework&lt;/a&gt; project. Instead, I should be out there looking for one to use as a basis for the thing. Here's pretty much what I wanted:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Fast and light&lt;br/&gt;&lt;br /&gt;When I'm writing software I like to write it once. Everything should work, and it should scale gracefully. This means the software should efficiently take the hardware as far as it can go, not the other way around. Sorry RoR, you're dismissed (currently). &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Stable&lt;br/&gt;&lt;br /&gt;I'll be using this framework for a number of production sites. It's got to be sturdy. There's nothing I hate more than restarting the server three times a day when it crashes suddenly.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Simple&lt;br/&gt;&lt;br /&gt;Kepty is a framework written in python. C and C++ are monstrous for web programming, but python offers the perfect combination of speed and elegance for the job. The Python/C API isn't as clear as the language. Since I don't want to spend too much time with it, I'd like the server code to be simple and easily extended.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Load-worthy&lt;br/&gt;&lt;br /&gt;Along with point #1, I like what I write to scale well. The server should handle load. The combined effects of a Slashdotting and Digg should barely register :)&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;In order to get this I started to look at a few frameworks. But first of all, the system:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;System:&lt;/h3&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Processor:&lt;/strong&gt;&lt;br/&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ cat /proc/cpuinfo&lt;br /&gt;processor       : 0&lt;br /&gt;vendor_id       : AuthenticAMD&lt;br /&gt;cpu family      : 15&lt;br /&gt;model           : 65&lt;br /&gt;model name      : Dual-Core AMD Opteron(tm) Processor 2210&lt;br /&gt;stepping        : 2&lt;br /&gt;cpu MHz         : 1800.042&lt;br /&gt;cache size      : 1024 KB&lt;br /&gt;physical id     : 0&lt;br /&gt;siblings        : 2&lt;br /&gt;core id         : 0&lt;br /&gt;cpu cores       : 2&lt;br /&gt;fpu             : yes&lt;br /&gt;fpu_exception   : yes&lt;br /&gt;cpuid level     : 1&lt;br /&gt;wp              : yes&lt;br /&gt;flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov &lt;br /&gt;                  pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt rdtscp lm &lt;br /&gt;                  3dno wext 3dnow pni cx16 lahf_lm cmp_legacy svm cr8_legacy&lt;br /&gt;bogomips        : 3603.65&lt;br /&gt;TLB size        : 1024 4K pages&lt;br /&gt;clflush size    : 64&lt;br /&gt;cache_alignment : 64&lt;br /&gt;address sizes   : 40 bits physical, 48 bits virtual&lt;br /&gt;power management: ts fid vid ttp tm stc&lt;br /&gt;&lt;br /&gt;processor       : 1 (same as above)&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Mainboard:&lt;/strong&gt; &lt;a href="http://www.asus.com/products.aspx?l1=9&amp;l2=39&amp;l3=0&amp;model=1271&amp;modelmenu=1"&gt;Asus KFN5-D SLI&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Memory:&lt;/strong&gt; &lt;a href="http://www.newegg.com/Product/Product.asp?Item=N82E16820145155"&gt;1GB Registered 667MHz Corsair&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;OS:&lt;/strong&gt; &lt;a href="http://www.slamd64.com/"&gt;Slamd64&lt;/a&gt; v 11.0&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;and the test description:&lt;br /&gt;&lt;br /&gt;Test #1: 100,000 requests, 100 concurrent, screenshot.jpg &lt;- 131KB&lt;br /&gt;Test #2: 100,000 requests, 20  concurrent, starter.png    &lt;- 1.5KB&lt;br /&gt;&lt;br /&gt;I wanted to get a test result for something that the server probably wouldn't get put through because bandwidth would get eaten up first, and then a test for a more real-world scenario. We're taking a look at these to replace the current server, so here are it's benchmarks:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Kepty Web Framework (current pure-python server)&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;I'll be replacing this server (which you can take a look at on the &lt;a href="http://sourceforge.net/projects/kepty"&gt;sourceforge project page&lt;/a&gt;) with a faster one... This is why we're doing the benchmarks...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Server Software:        Kepty-1.0&lt;br /&gt;Server Hostname:        127.0.0.1&lt;br /&gt;Server Port:            2620&lt;br /&gt;&lt;br /&gt;Document Path:          /static/screenshot.jpg&lt;br /&gt;Document Length:        133175 bytes&lt;br /&gt;&lt;br /&gt;Concurrency Level:      100&lt;br /&gt;Time taken for tests:   166.201361 seconds&lt;br /&gt;Complete requests:      100000&lt;br /&gt;Failed requests:        0&lt;br /&gt;Write errors:           0&lt;br /&gt;Total transferred:      13342500000 bytes&lt;br /&gt;HTML transferred:       13317500000 bytes&lt;br /&gt;Requests per second:    601.68 [#/sec] (mean)&lt;br /&gt;Time per request:       166.201 [ms] (mean)&lt;br /&gt;Time per request:       1.662 [ms] (mean, across all concurrent requests)&lt;br /&gt;Transfer rate:          78397.59 [Kbytes/sec] received&lt;br /&gt;&lt;br /&gt;Connection Times (ms)&lt;br /&gt;              min  mean[+/-sd] median   max&lt;br /&gt;Connect:        0   92 696.0      0   45004&lt;br /&gt;Processing:     1   39 1123.9     18  106328&lt;br /&gt;Waiting:        0   39 1123.8     18  106327&lt;br /&gt;Total:          5  132 1434.8     18  115331&lt;br /&gt;&lt;br /&gt;Percentage of the requests served within a certain time (ms)&lt;br /&gt;  50%     18&lt;br /&gt;  66%     19&lt;br /&gt;  75%     20&lt;br /&gt;  80%     21&lt;br /&gt;  90%     23&lt;br /&gt;  95%     26&lt;br /&gt;  98%   3018&lt;br /&gt;  99%   3020&lt;br /&gt; 100%  115331 (longest request)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;We bombed here... Concurrent users aren't handled fast enough, but we didn't do &lt;strong&gt;too&lt;/strong&gt; badly :)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Benchmarking 127.0.0.1 (be patient)&lt;br /&gt;Completed 10000 requests&lt;br /&gt;Completed 20000 requests&lt;br /&gt;Completed 30000 requests&lt;br /&gt;Completed 40000 requests&lt;br /&gt;Completed 50000 requests&lt;br /&gt;Completed 60000 requests&lt;br /&gt;Completed 70000 requests&lt;br /&gt;Completed 80000 requests&lt;br /&gt;Completed 90000 requests&lt;br /&gt;Finished 100000 requests&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Server Software:        Kepty-1.0&lt;br /&gt;Server Hostname:        127.0.0.1&lt;br /&gt;Server Port:            2620&lt;br /&gt;&lt;br /&gt;Document Path:          /static/starter.png&lt;br /&gt;Document Length:        1478 bytes&lt;br /&gt;&lt;br /&gt;Concurrency Level:      20&lt;br /&gt;Time taken for tests:   74.292005 seconds&lt;br /&gt;Complete requests:      100000&lt;br /&gt;Failed requests:        0&lt;br /&gt;Write errors:           0&lt;br /&gt;Total transferred:      172500000 bytes&lt;br /&gt;HTML transferred:       147800000 bytes&lt;br /&gt;Requests per second:    1346.04 [#/sec] (mean)&lt;br /&gt;Time per request:       14.858 [ms] (mean)&lt;br /&gt;Time per request:       0.743 [ms] (mean, across all concurrent requests)&lt;br /&gt;Transfer rate:          2267.50 [Kbytes/sec] received&lt;br /&gt;&lt;br /&gt;Connection Times (ms)&lt;br /&gt;              min  mean[+/-sd] median   max&lt;br /&gt;Connect:        0    4 186.6      0   21001&lt;br /&gt;Processing:     0    9  31.8      8    3250&lt;br /&gt;Waiting:        0    9  31.7      8    3250&lt;br /&gt;Total:          0   13 190.7      8   21669&lt;br /&gt;&lt;br /&gt;Percentage of the requests served within a certain time (ms)&lt;br /&gt;  50%      8&lt;br /&gt;  66%      9&lt;br /&gt;  75%      9&lt;br /&gt;  80%      9&lt;br /&gt;  90%     10&lt;br /&gt;  95%     10&lt;br /&gt;  98%     10&lt;br /&gt;  99%     13&lt;br /&gt; 100%  21669 (longest request)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;The 21 second wait time on that longest request kind of gets to me... Can anyone out there explain what that actually means in the real world? But in any case, Kepty still outperforms pretty much every other pure-python server out there... It's just not &lt;b&gt;good enough&lt;/b&gt; for me.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Now we get on to the fun stuff:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Apache&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;The powerhouse of the web world. Apache is an EXTREMELY popular server, and it's got the support of pretty much every professional system administrator out there. It's highly extensible with it's API, and it's just what I'm NOT looking for here (don't yell at me for the low scores, this is a specialized task, damnit!). &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Speed/Lightness:&lt;/strong&gt; 4/10 (2 tests avg 2594.07 Req/S)&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Stability:&lt;/strong&gt; 10/10&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Simplicity:&lt;/strong&gt; 3/10&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Load-handling:&lt;/strong&gt; 7/10&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Server Software:        Apache/1.3.37&lt;br /&gt;Server Hostname:        localhost&lt;br /&gt;Server Port:            80&lt;br /&gt;&lt;br /&gt;Document Path:          /screenshot.jpg&lt;br /&gt;Document Length:        133175 bytes&lt;br /&gt;&lt;br /&gt;Concurrency Level:      100&lt;br /&gt;Time taken for tests:   78.140494 seconds&lt;br /&gt;Complete requests:      100000&lt;br /&gt;Failed requests:        0&lt;br /&gt;Write errors:           0&lt;br /&gt;Total transferred:      13343133704 bytes&lt;br /&gt;HTML transferred:       13318032700 bytes&lt;br /&gt;Requests per second:    1279.75 [#/sec] (mean)&lt;br /&gt;Time per request:       78.140 [ms] (mean)&lt;br /&gt;Time per request:       0.781 [ms] (mean, across all concurrent requests)&lt;br /&gt;Transfer rate:          166756.09 [Kbytes/sec] received&lt;br /&gt;&lt;br /&gt;Connection Times (ms)&lt;br /&gt;              min  mean[+/-sd] median   max&lt;br /&gt;Connect:        0    1   1.2      1      16&lt;br /&gt;Processing:     1   76   6.5     77     116&lt;br /&gt;Waiting:        0    9  13.0      5      75&lt;br /&gt;Total:          7   77   6.7     79     118&lt;br /&gt;&lt;br /&gt;Percentage of the requests served within a certain time (ms)&lt;br /&gt;  50%     79&lt;br /&gt;  66%     81&lt;br /&gt;  75%     82&lt;br /&gt;  80%     83&lt;br /&gt;  90%     84&lt;br /&gt;  95%     85&lt;br /&gt;  98%     88&lt;br /&gt;  99%     94&lt;br /&gt; 100%    118 (longest request)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Benchmarking localhost (be patient)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Server Software:        Apache/1.3.37&lt;br /&gt;Server Hostname:        localhost&lt;br /&gt;Server Port:            80&lt;br /&gt;&lt;br /&gt;Document Path:          /starter.png&lt;br /&gt;Document Length:        1478 bytes&lt;br /&gt;&lt;br /&gt;Concurrency Level:      20&lt;br /&gt;Time taken for tests:   25.588280 seconds&lt;br /&gt;Complete requests:      100000&lt;br /&gt;Failed requests:        0&lt;br /&gt;Write errors:           0&lt;br /&gt;Total transferred:      172401724 bytes&lt;br /&gt;HTML transferred:       147801478 bytes&lt;br /&gt;Requests per second:    3908.04 [#/sec] (mean)&lt;br /&gt;Time per request:       5.118 [ms] (mean)&lt;br /&gt;Time per request:       0.256 [ms] (mean, across all concurrent requests)&lt;br /&gt;Transfer rate:          6579.61 [Kbytes/sec] received&lt;br /&gt;&lt;br /&gt;Connection Times (ms)&lt;br /&gt;              min  mean[+/-sd] median   max&lt;br /&gt;Connect:        0    0   0.7      0      13&lt;br /&gt;Processing:     1    4   0.8      4      17&lt;br /&gt;Waiting:        0    1   0.8      2      14&lt;br /&gt;Total:          1    4   1.1      5      21&lt;br /&gt;WARNING: The median and mean for the waiting time are not within a normal deviation&lt;br /&gt;        These results are probably not that reliable.&lt;br /&gt;&lt;br /&gt;Percentage of the requests served within a certain time (ms)&lt;br /&gt;  50%      5&lt;br /&gt;  66%      5&lt;br /&gt;  75%      5&lt;br /&gt;  80%      5&lt;br /&gt;  90%      6&lt;br /&gt;  95%      6&lt;br /&gt;  98%      6&lt;br /&gt;  99%      6&lt;br /&gt; 100%     21 (longest request)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;lighttpd&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;This server continues to gain popularity, much due to the fact that RoR users find it a good way to set up when they're using fCGI. It's faster than Apache, simpler, and just as stable. It does aim, however, to maintain a full feature set, so it gets lower scores for simplicity. &lt;br /&gt;&lt;br /&gt;The first time I've played around with lighttpd was today, and I'll have to say that I'm impressed. It maintained a higher footprint during the load than the next two servers (no surpise), and that does score against it, but the speed with which it handled the requests was amazing. If I had more time, or maybe more interest in something with so many features, I'd be more than willing to use this program. Heck, perhaps I'll make a source contribution to them in the future.&lt;br /&gt; &lt;br /&gt;&lt;strong&gt;Speed/Lightness:&lt;/strong&gt; 9/10 (2 tests avg 6985.48 Req/S)&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Stability:&lt;/strong&gt; 9/10&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Simplicity:&lt;/strong&gt; 5/10&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Load-handling:&lt;/strong&gt; 8/10&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Benchmarking localhost (be patient)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Server Software:        lighttpd/1.4.13&lt;br /&gt;Server Hostname:        localhost&lt;br /&gt;Server Port:            2623&lt;br /&gt;&lt;br /&gt;Document Path:          /screenshot.jpg&lt;br /&gt;Document Length:        133175 bytes&lt;br /&gt;&lt;br /&gt;Concurrency Level:      100&lt;br /&gt;Time taken for tests:   25.332170 seconds&lt;br /&gt;Complete requests:      100000&lt;br /&gt;Failed requests:        0&lt;br /&gt;Write errors:           0&lt;br /&gt;Total transferred:      13343233961 bytes&lt;br /&gt;HTML transferred:       13318432225 bytes&lt;br /&gt;Requests per second:    3947.55 [#/sec] (mean)&lt;br /&gt;Time per request:       25.332 [ms] (mean)&lt;br /&gt;Time per request:       0.253 [ms] (mean, across all concurrent requests)&lt;br /&gt;Transfer rate:          514385.50 [Kbytes/sec] received&lt;br /&gt;&lt;br /&gt;Connection Times (ms)&lt;br /&gt;              min  mean[+/-sd] median   max&lt;br /&gt;Connect:        0    0   1.2      0      31&lt;br /&gt;Processing:     7   24   3.0     24      51&lt;br /&gt;Waiting:        0    1   1.5      2      30&lt;br /&gt;Total:          8   24   3.4     24      65&lt;br /&gt;&lt;br /&gt;Percentage of the requests served within a certain time (ms)&lt;br /&gt;  50%     24&lt;br /&gt;  66%     24&lt;br /&gt;  75%     25&lt;br /&gt;  80%     25&lt;br /&gt;  90%     25&lt;br /&gt;  95%     27&lt;br /&gt;  98%     40&lt;br /&gt;  99%     44&lt;br /&gt; 100%     65 (longest request)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Server Software:        lighttpd/1.4.13&lt;br /&gt;Server Hostname:        localhost&lt;br /&gt;Server Port:            2623&lt;br /&gt;&lt;br /&gt;Document Path:          /starter.png&lt;br /&gt;Document Length:        1478 bytes&lt;br /&gt;&lt;br /&gt;Concurrency Level:      20&lt;br /&gt;Time taken for tests:   9.976645 seconds&lt;br /&gt;Complete requests:      100000&lt;br /&gt;Failed requests:        0&lt;br /&gt;Write errors:           0&lt;br /&gt;Total transferred:      172200000 bytes&lt;br /&gt;HTML transferred:       147800000 bytes&lt;br /&gt;Requests per second:    10023.41 [#/sec] (mean)&lt;br /&gt;Time per request:       1.995 [ms] (mean)&lt;br /&gt;Time per request:       0.100 [ms] (mean, across all concurrent requests)&lt;br /&gt;Transfer rate:          16855.77 [Kbytes/sec] received&lt;br /&gt;&lt;br /&gt;Connection Times (ms)&lt;br /&gt;              min  mean[+/-sd] median   max&lt;br /&gt;Connect:        0    0   0.2      0      12&lt;br /&gt;Processing:     0    1   0.8      1      19&lt;br /&gt;Waiting:        0    0   0.5      0      17&lt;br /&gt;Total:          0    1   0.9      1      19&lt;br /&gt;&lt;br /&gt;Percentage of the requests served within a certain time (ms)&lt;br /&gt;  50%      1&lt;br /&gt;  66%      2&lt;br /&gt;  75%      2&lt;br /&gt;  80%      2&lt;br /&gt;  90%      2&lt;br /&gt;  95%      2&lt;br /&gt;  98%      3&lt;br /&gt;  99%      4&lt;br /&gt; 100%     19 (longest request)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;boa&lt;/h3&gt;&lt;br /&gt;&lt;strong&gt;Speed/Lightness:&lt;/strong&gt; 7/10 (2 tests avg 4598.73 Req/S)&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Stability:&lt;/strong&gt; 9/10&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Simplicity:&lt;/strong&gt; 7/10&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Load-handling:&lt;/strong&gt; 7/10&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;According to it's &lt;a href="http://en.wikipedia.org/wiki/Boa_%28web_server%29"&gt;wikipedia entry&lt;/a&gt; the boa server is used for serving up images on slashdot. This wouldn't surprise me, other than the fact that thttpd beat it out pretty badly, even with the small files. Without HTTP/1.1 connection support though, thttpd might not have gotten that far. Cruel world, but boa hasn't had a release in a while (latest is 2002), and it's about time it gets an update. The code base is small, but not very well commented, which scores against it in simplicity.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Benchmarking localhost (be patient)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Server Software:        Boa/0.94.13&lt;br /&gt;Server Hostname:        localhost&lt;br /&gt;Server Port:            2622&lt;br /&gt;&lt;br /&gt;Document Path:          /screenshot.jpg&lt;br /&gt;Document Length:        133175 bytes&lt;br /&gt;&lt;br /&gt;Concurrency Level:      100&lt;br /&gt;Time taken for tests:   99.204866 seconds&lt;br /&gt;Complete requests:      100000&lt;br /&gt;Failed requests:        0&lt;br /&gt;Write errors:           0&lt;br /&gt;Total transferred:      13336700000 bytes&lt;br /&gt;HTML transferred:       13317500000 bytes&lt;br /&gt;Requests per second:    1008.02 [#/sec] (mean)&lt;br /&gt;Time per request:       99.205 [ms] (mean)&lt;br /&gt;Time per request:       0.992 [ms] (mean, across all concurrent requests)&lt;br /&gt;Transfer rate:          131285.11 [Kbytes/sec] received&lt;br /&gt;&lt;br /&gt;Connection Times (ms)&lt;br /&gt;              min  mean[+/-sd] median   max&lt;br /&gt;Connect:        0    0   0.2      0       8&lt;br /&gt;Processing:    41   98  12.6     91     189&lt;br /&gt;Waiting:        0    2   1.1      2      28&lt;br /&gt;Total:         41   98  12.6     91     189&lt;br /&gt;&lt;br /&gt;Percentage of the requests served within a certain time (ms)&lt;br /&gt;  50%     91&lt;br /&gt;  66%    109&lt;br /&gt;  75%    111&lt;br /&gt;  80%    111&lt;br /&gt;  90%    114&lt;br /&gt;  95%    118&lt;br /&gt;  98%    123&lt;br /&gt;  99%    133&lt;br /&gt; 100%    189 (longest request)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Benchmarking localhost (be patient)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Server Software:        Boa/0.94.13&lt;br /&gt;Server Hostname:        localhost&lt;br /&gt;Server Port:            2622&lt;br /&gt;&lt;br /&gt;Document Path:          /starter.png&lt;br /&gt;Document Length:        1478 bytes&lt;br /&gt;&lt;br /&gt;Concurrency Level:      20&lt;br /&gt;Time taken for tests:   12.210854 seconds&lt;br /&gt;Complete requests:      100000&lt;br /&gt;Failed requests:        0&lt;br /&gt;Write errors:           0&lt;br /&gt;Total transferred:      166806672 bytes&lt;br /&gt;HTML transferred:       147805912 bytes&lt;br /&gt;Requests per second:    8189.44 [#/sec] (mean)&lt;br /&gt;Time per request:       2.442 [ms] (mean)&lt;br /&gt;Time per request:       0.122 [ms] (mean, across all concurrent requests)&lt;br /&gt;Transfer rate:          13340.34 [Kbytes/sec] received&lt;br /&gt;&lt;br /&gt;Connection Times (ms)&lt;br /&gt;              min  mean[+/-sd] median   max&lt;br /&gt;Connect:        0    0   0.8      0      19&lt;br /&gt;Processing:     0    1   1.2      2      20&lt;br /&gt;Waiting:        0    0   0.8      0      18&lt;br /&gt;Total:          0    1   1.6      2      23&lt;br /&gt;&lt;br /&gt;Percentage of the requests served within a certain time (ms)&lt;br /&gt;  50%      2&lt;br /&gt;  66%      2&lt;br /&gt;  75%      2&lt;br /&gt;  80%      2&lt;br /&gt;  90%      4&lt;br /&gt;  95%      4&lt;br /&gt;  98%      5&lt;br /&gt;  99%      6&lt;br /&gt; 100%     23 (longest request)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;thttpd&lt;/h3&gt;&lt;br /&gt;&lt;strong&gt;Speed/Lightness:&lt;/strong&gt; 7/10 (2 tests avg 5364.12 Req/S)&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Stability:&lt;/strong&gt; 7/10&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Simplicity:&lt;/strong&gt; 9/10&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Load-handling:&lt;/strong&gt; 9/10&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;thttpd is a wonderfully written little server. The code is well documented and there isn't too much of it. It supports the base HTTP/1.1 standard, unlike boa (HTTP/1.0), which leaves room to expand it. It handled the 100 vs 20 concurrency very well,so I give it a 10 in the load-handling list (a thoroughput of around 237,000 KB/sec is more than enough to make the bottleneck your bandwidth). It puts quite a bit into a very small package...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Server Software:        thttpd/2.25b&lt;br /&gt;Server Hostname:        localhost&lt;br /&gt;Server Port:            2621&lt;br /&gt;&lt;br /&gt;Document Path:          /screenshot.jpg&lt;br /&gt;Document Length:        133175 bytes&lt;br /&gt;&lt;br /&gt;Concurrency Level:      100&lt;br /&gt;Time taken for tests:   54.815574 seconds&lt;br /&gt;Complete requests:      100000&lt;br /&gt;Failed requests:        0&lt;br /&gt;Write errors:           0&lt;br /&gt;Total transferred:      13340133400 bytes&lt;br /&gt;HTML transferred:       13317633175 bytes&lt;br /&gt;Requests per second:    1824.30 [#/sec] (mean)&lt;br /&gt;Time per request:       54.816 [ms] (mean)&lt;br /&gt;Time per request:       0.548 [ms] (mean, across all concurrent requests)&lt;br /&gt;Transfer rate:          237660.08 [Kbytes/sec] received&lt;br /&gt;&lt;br /&gt;Connection Times (ms)&lt;br /&gt;              min  mean[+/-sd] median   max&lt;br /&gt;Connect:        0    1   1.1      1      28&lt;br /&gt;Processing:     5   52  11.7     61      94&lt;br /&gt;Waiting:        0    3   2.1      3      38&lt;br /&gt;Total:          5   54  11.9     63      96&lt;br /&gt;&lt;br /&gt;Percentage of the requests served within a certain time (ms)&lt;br /&gt;  50%     63&lt;br /&gt;  66%     63&lt;br /&gt;  75%     64&lt;br /&gt;  80%     64&lt;br /&gt;  90%     64&lt;br /&gt;  95%     65&lt;br /&gt;  98%     67&lt;br /&gt;  99%     71&lt;br /&gt; 100%     96 (longest request)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Benchmarking localhost (be patient)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Server Software:        thttpd/2.25b&lt;br /&gt;Server Hostname:        localhost&lt;br /&gt;Server Port:            2621&lt;br /&gt;&lt;br /&gt;Document Path:          /starter.png&lt;br /&gt;Document Length:        1478 bytes&lt;br /&gt;&lt;br /&gt;Concurrency Level:      20&lt;br /&gt;Time taken for tests:   11.230982 seconds&lt;br /&gt;Complete requests:      100000&lt;br /&gt;Failed requests:        0&lt;br /&gt;Write errors:           0&lt;br /&gt;Total transferred:      170000000 bytes&lt;br /&gt;HTML transferred:       147800000 bytes&lt;br /&gt;Requests per second:    8903.94 [#/sec] (mean)&lt;br /&gt;Time per request:       2.246 [ms] (mean)&lt;br /&gt;Time per request:       0.112 [ms] (mean, across all concurrent requests)&lt;br /&gt;Transfer rate:          14781.88 [Kbytes/sec] received&lt;br /&gt;&lt;br /&gt;Connection Times (ms)&lt;br /&gt;              min  mean[+/-sd] median   max&lt;br /&gt;Connect:        0    0   0.5      0      12&lt;br /&gt;Processing:     0    1   0.9      1      14&lt;br /&gt;Waiting:        0    0   1.0      1      13&lt;br /&gt;Total:          0    1   1.2      1      18&lt;br /&gt;&lt;br /&gt;Percentage of the requests served within a certain time (ms)&lt;br /&gt;  50%      1&lt;br /&gt;  66%      2&lt;br /&gt;  75%      2&lt;br /&gt;  80%      2&lt;br /&gt;  90%      3&lt;br /&gt;  95%      4&lt;br /&gt;  98%      5&lt;br /&gt;  99%      5&lt;br /&gt; 100%     18 (longest request)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Results&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Apache&lt;/b&gt;: 24/40 (60%)&lt;br /&gt;&lt;b&gt;lighttpd&lt;/b&gt;: 31/40 (75.5%) &lt;br /&gt;&lt;b&gt;boa&lt;/b&gt;: 30/40 (75%)&lt;br /&gt;&lt;b&gt;thttpd&lt;/b&gt;: 32/40 (80%)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;For this purpose&lt;/strong&gt; thttpd looks like it's the winner. This is an open source project though, and I would like to know what the community thinks should be done first. Are there other systems you think I should benchmark? Was I wrong about something that I should adjust for? I'll start the project sometime next week, so give me input!&lt;br /&gt;&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-116191907316000759?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/116191907316000759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=116191907316000759' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/116191907316000759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/116191907316000759'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/10/lighttpd-apache-boa-thttpd-benchmarks.html' title='lighttpd, apache, boa, thttpd benchmarks - A quick server for Kepty'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-116027363786685810</id><published>2006-10-07T19:09:00.000-07:00</published><updated>2006-11-15T21:19:55.206-07:00</updated><title type='text'>Fluxbox .9 to 1.0rc2</title><content type='html'>I just made the switch from a development .9 version of &lt;a href="http://fluxbox.sourceforge.net"&gt;Fluxbox&lt;/a&gt; to the second release candidate for v 1.0. Nicely done Fluxbox developers! Everything is very responsive and I'm glad you brought back the external tabs. I'm happy.&lt;br /&gt;&lt;br /&gt;But, for those of you who set up your Fluxbox configuration a while ago, and happened to modify the placement of your minimize, maximize and close buttons, it's a shock to see them reset to the standard Windows positions. In any case, the configuration settings are in your ~/.fluxbox/init file:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;session.screen0.titlebar.left: Close Minimize Maximize&lt;br /&gt;session.screen0.titlebar.right: Stick&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The above are adjusted for my preferences (as if that wasn't obvious) so change them to your preferred setting.&lt;br /&gt;&lt;br /&gt;Take it easy all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-116027363786685810?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/116027363786685810/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=116027363786685810' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/116027363786685810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/116027363786685810'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/10/fluxbox-9-to-10rc2.html' title='Fluxbox .9 to 1.0rc2'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115982440585897426</id><published>2006-10-02T14:21:00.000-07:00</published><updated>2006-11-15T21:19:55.108-07:00</updated><title type='text'>Kepty WAF scaffolding</title><content type='html'>The Kepty web application framework got a new addition today... Scaffolding. It's been planned for a while, but I was trying to avoid it until all the other pieces were getting together properly. Database-generated forms are great, but they also took too much away from the user end. The forms generated by the scaffold are code-based, meaning you can modify them as you please. With my current working application I have a database with a table named "posts." I simply use this command:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;kepty scaffold posts&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And I get an application for modifying and browsing the posts table. It's mounted as name: posts, location: /posts&lt;br /&gt;automatically. Browse to http://serveraddress/posts and you get this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/screenshot.6.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/screenshot.5.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It's a start. My intentions for the scaffolding process with the kepty WAF are to keep something that can actually be used in production that's professional and easily modified (code generation at a low level instead of something like form(table), although possible). In any case, take a look at the sourceforge project page for more.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115982440585897426?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115982440585897426/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115982440585897426' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115982440585897426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115982440585897426'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/10/kepty-waf-scaffolding.html' title='Kepty WAF scaffolding'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115966322020796928</id><published>2006-09-30T17:32:00.000-07:00</published><updated>2006-11-15T21:19:55.019-07:00</updated><title type='text'>Use __import__ on an actual path...</title><content type='html'>Now, this is definitely not the wisest thing to do, but sometimes you'll want to simply import a module when you know its path. The built in __import__ function won't let you go about doing this. If you're looking for something that works, but might be a little dirty, I've got the trick for you. &lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;# 2006 James Kassemi, (james@tweekedideas.com)&lt;br /&gt;# ================================================&lt;br /&gt;# Import all from all modules in this directory...&lt;br /&gt;&lt;br /&gt;import os, imp&lt;br /&gt;&lt;br /&gt;def import_path(path, return_name=False):&lt;br /&gt;    ''' Use like __import__, but with the path to a module. '''&lt;br /&gt;    if os.path.isdir(path):&lt;br /&gt;        mn = path.split('/')[-1]&lt;br /&gt;        path = os.path.join(path, '__init__.py')&lt;br /&gt;        if not os.path.exists(path):&lt;br /&gt;            path += 'c'&lt;br /&gt;    else:&lt;br /&gt;        mn = path.split('/')[-1]&lt;br /&gt;        mn = mn[:mn.rfind('.')]&lt;br /&gt;&lt;br /&gt;    suffixes = imp.get_suffixes()&lt;br /&gt;    for suffix, mode, type in suffixes:&lt;br /&gt;        if path.endswith(suffix):&lt;br /&gt;            fp = open(path, mode)&lt;br /&gt;            m = imp.load_module(mn, fp, path, (suffix, mode, type))&lt;br /&gt;            fp.close()&lt;br /&gt;            if return_name: m = (m, mn)&lt;br /&gt;            return m&lt;br /&gt;    raise ImportError("Not a module: %s" % path)&lt;br /&gt;&lt;br /&gt;focal_dir = os.path.dirname(__file__)&lt;br /&gt;for f in os.listdir(focal_dir):&lt;br /&gt;    if f.startswith('.') or f.startswith('_'): continue&lt;br /&gt;    temp_mod = import_path(os.path.join(focal_dir, f))&lt;br /&gt;    for k, v in temp_mod.__dict__.iteritems():&lt;br /&gt;        globals()[k] = v&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Place the above contents in an __init__.py file and it will automatically load all of the contents from all of the sibling files in the directory. No more specifying an __all__, either, as you can quickly hack this to just import the module itself as well:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;focal_dir = os.path.dirname(__file__)&lt;br /&gt;for f in os.listdir(focal_dir):&lt;br /&gt;    if f.startswith('.') or f.startswith('_'): continue&lt;br /&gt;    module, name = import_path(os.path.join(focal_dir, f), True)&lt;br /&gt;    globals()[name] = module    &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now there are some concerns with approaching the problem this way... Mainly compatibility with other import statements in the same namespace, sys.modules mapping, etc, but it will work when you're in a pinch.&lt;br /&gt;&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115966322020796928?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115966322020796928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115966322020796928' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115966322020796928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115966322020796928'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/09/use-import-on-actual-path.html' title='Use __import__ on an actual path...'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115906387346489794</id><published>2006-09-23T19:03:00.000-07:00</published><updated>2006-11-15T21:19:54.922-07:00</updated><title type='text'>Use GPL v. 2 in your application...</title><content type='html'>Those of us that write open source applications have something to worry about, and it comes in the form of the GPL agreement:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;one line to give the program's name and an idea of what it does.&lt;br /&gt;Copyright (C) yyyy  name of author&lt;br /&gt;&lt;br /&gt;This program is free software; you can redistribute it and/or&lt;br /&gt;modify it under the terms of the GNU General Public License&lt;br /&gt;as published by the Free Software Foundation; &lt;b&gt;either version 2&lt;br /&gt;of the License, or (at your option) any later version.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This program is distributed in the hope that it will be useful,&lt;br /&gt;but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;GNU General Public License for more details.&lt;br /&gt;&lt;br /&gt;You should have received a copy of the GNU General Public License&lt;br /&gt;along with this program; if not, write to the Free Software&lt;br /&gt;Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Notice the statement in bold... Some of us are quite comfortable with version 2 at the moment, and version 3 is starting a pretty nice controversy (search slashdot for articles related to gpl v3 and read up).&lt;br /&gt;&lt;br /&gt;Do yourself a favor when writing an open source application under the GPL license and avoid the issues with the upcoming GPL v3. Use this text instead of what you're getting from the gnu site at the moment:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;    Copyright (C) YEAR YOUR_NAME&lt;br /&gt;&lt;br /&gt;    This program is free software; you can redistribute it and/or&lt;br /&gt;    modify it under the terms of the GNU General Public License Version 2,&lt;br /&gt;    as published by the Free Software Foundation.&lt;br /&gt;&lt;br /&gt;    This program is distributed in the hope that it will be useful,&lt;br /&gt;    but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;    GNU General Public License for more details.&lt;br /&gt;&lt;br /&gt;    You should have received a copy of the GNU General Public License&lt;br /&gt;    along with this program; if not, write to the Free Software&lt;br /&gt;    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Change is scary, remember?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115906387346489794?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115906387346489794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115906387346489794' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115906387346489794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115906387346489794'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/09/use-gpl-v-2-in-your-application.html' title='Use GPL v. 2 in your application...'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115889647367650383</id><published>2006-09-21T20:31:00.000-07:00</published><updated>2006-11-15T21:19:54.841-07:00</updated><title type='text'>Soon forget: Daily impact</title><content type='html'>Ah. The event that most hit me this evening came from what seems an unlikely source, a Pearl Jam song, "Soon forget." Not certain whether or not it's a cover, but that's beside the point at the moment...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;"&lt;/b&gt;&lt;i&gt;Sorry is the fool who trades his soul for a corvette,&lt;br /&gt;Thinks he'll get the girl, he'll only get the mechanic.&lt;br /&gt;What's missing? He's living a day he'll soon forget.&lt;br /&gt;&lt;br /&gt;That's one more time around, the sun is going down,&lt;br /&gt;The moon is out, but he's drunk and shouting, putting people down.&lt;br /&gt;He's pissing, he's living a day he'll soon forget.&lt;br /&gt;&lt;br /&gt;Counts his money every morning,&lt;br /&gt;the only thing that keeps him horny. &lt;br /&gt;Locked in a giant house, that's alarming.&lt;br /&gt;The townsfolk, they all laugh.&lt;br /&gt;&lt;br /&gt;Sorry is the fool who trades his love for a high-rise rent.&lt;br /&gt;Seems the more you make equals the loneliness you get,&lt;br /&gt;and it's fitting, he's barely living, a day he'll soon forget.&lt;br /&gt;&lt;br /&gt;That's one more time around, there is not a sound,&lt;br /&gt;he's lying dead clutching benjamins.&lt;br /&gt;Never put the money down. He's stiffening, we're all&lt;br /&gt;whistling, a man we'll soon forget.  &lt;br /&gt;&lt;/i&gt;&lt;b&gt;"&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Although a bit crudely put for such a slow, harmonious piece,&lt;br /&gt;I tend to trust the wealthy, drugged up artists' interpretation&lt;br /&gt;of money and success more than I would Mr. Average Joe. Although&lt;br /&gt;I'm not necessarily rolling in the dough, I do long to have&lt;br /&gt;an easy life. &lt;br /&gt;&lt;br /&gt;&lt;i&gt;A man we'll soon forget...&lt;/i&gt; Hopefully not reader, hopefully not.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115889647367650383?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115889647367650383/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115889647367650383' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115889647367650383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115889647367650383'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/09/soon-forget-daily-impact.html' title='Soon forget: Daily impact'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115672641129513323</id><published>2006-08-27T17:45:00.000-07:00</published><updated>2006-11-15T21:19:54.744-07:00</updated><title type='text'>To control structures: stop chaning! </title><content type='html'>**Growl**&lt;br /&gt;&lt;br /&gt;Just got a little peeved today. I'm picking up Ruby for my job, and as I go through the online Ruby book I come across the control structures. Standard if/else if/else statements... And Ruby's just happens to be:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;if something&lt;br /&gt;    do&lt;br /&gt;elsif something&lt;br /&gt;    do&lt;br /&gt;else&lt;br /&gt;    do&lt;br /&gt;end&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now, these are commands that are issued hundreds of times a day by programmers everywhere. Actually having to THINK about how to do your control structures will take valuable time away from placing that concept into code... Why the heck can't we keep certain things standard?&lt;br /&gt;&lt;br /&gt;C/C++/Javascript:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;if(something){&lt;br /&gt;    do;&lt;br /&gt;}else if(something){&lt;br /&gt;    do;&lt;br /&gt;}else{&lt;br /&gt;    do;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Python:&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;if something:&lt;br /&gt;    do&lt;br /&gt;elif something:&lt;br /&gt;    do&lt;br /&gt;else:&lt;br /&gt;    do&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Okay. Shame on you python and ruby. The short cuts mean less effort typing, but much more effort for those of us (most of us) who have to code between languages daily. Ah. Daily rant.&lt;br /&gt;&lt;br /&gt;Good day,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115672641129513323?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115672641129513323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115672641129513323' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115672641129513323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115672641129513323'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/08/to-control-structures-stop-chaning.html' title='To control structures: stop chaning! &lt;RANT&gt;'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115642714271501179</id><published>2006-08-24T06:39:00.000-07:00</published><updated>2006-11-15T21:19:54.643-07:00</updated><title type='text'>A cocky little spammer.</title><content type='html'>I've gotten a load of these spams recently, all of which contain an image which seems &lt;br /&gt;designed to evade some kind of spam-detection OCR...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/temp.0.gif"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/temp.0.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I can do a bit more research, but right now I don't really have the time. What the hell is the purpose of doing this? Does current spam protection actually scan each image? How many of us have anything installed that's not just a simple bayesian-based detection scheme? Where can &lt;br /&gt;I get a hold of it? And wouldn't adding the distortions to that image take a little too much time that the spammer should know to avoid (Read my blog. I know about dynamic image creation and the time it takes, by the way).&lt;br /&gt;&lt;br /&gt;I should probably add the following text was attached in an effort to bypass it:&lt;br /&gt;&lt;br /&gt;"&lt;br /&gt;&lt;span style="font-style:italic;"&gt;your meds directly from the manufacturer,&lt;br /&gt;see attach for details&lt;br /&gt;followed Commander Alphamega out, leaving Floyd prisoner in the chair.&lt;br /&gt;the seconds to doomsday.&lt;/span&gt;&lt;br /&gt;"&lt;br /&gt;&lt;br /&gt;So, as is pretty obvious, this was flagged immediately. Probably a combo of the meds, manufacturer and length of the message... But wow.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115642714271501179?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115642714271501179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115642714271501179' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115642714271501179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115642714271501179'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/08/cocky-little-spammer.html' title='A cocky little spammer.'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115498066277548362</id><published>2006-08-07T12:57:00.000-07:00</published><updated>2006-11-15T21:19:54.483-07:00</updated><title type='text'>...</title><content type='html'>who are the ones with the __influence?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115498066277548362?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115498066277548362/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115498066277548362' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115498066277548362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115498066277548362'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/08/blog-post.html' title='...'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115406877680643181</id><published>2006-07-27T23:33:00.000-07:00</published><updated>2006-11-15T21:19:54.366-07:00</updated><title type='text'>Time Travelers</title><content type='html'>Your efforts lack recognition, an absence fueling the torturing fires of your mind. Only death carries the extinguisher - an obvious and indisputable fact fixed to the forefront of your consciousness. To you, my fellow time traveler, I give my wishes, for better times, graspable brilliance, and remarkable voyages. &lt;br /&gt;&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115406877680643181?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115406877680643181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115406877680643181' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115406877680643181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115406877680643181'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/07/time-travelers.html' title='Time Travelers'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115386194995337354</id><published>2006-07-25T14:01:00.000-07:00</published><updated>2006-11-15T21:19:54.280-07:00</updated><title type='text'>Diet Mountain Dew, Where Art Thou?</title><content type='html'>Mountain dew is my blood. Five or six tasty, energy boosting 2-liters enter my system daily. The juice fills my body with warmth, wakes me up, and just makes me pretty damn happy. Somehow it even gets rid of those headaches I get when I haven't had it for a while :) After a 75 pound experience with regular mountain dew I decided to switch to the diet stuff. A year later the weight is gone and my desire for the substance only stronger.&lt;br /&gt;&lt;br /&gt;Imagine my surprise then when I walk into the supermarket and the stuff isn't there! None of it. Okay, I thought. A switch to good ol' diet pepsi in the interum would be fine... No. Turns out I need the green-yellow juice. Nothing else will do. Diet Dr Pepper sticks to my throat, Diet Pepsi doesn't have the kick (nor do Diet Orange Soda or Diet A&amp;W)... What's a simple programmer to do? Apparently my hunger for this stuff has caused a short in supplies in the Southwestern US. What else explains it? I stumbled into about nine different supermarkets today, and finally picked off the last that one of them had (5 two-liters), so I'm good for today... But what about tomorrow?&lt;br /&gt;&lt;br /&gt;If you are a representative of the Pepsi corporation, I beg that you a) send more supplies to the Albuquerque area immediately, and b) sponsor me. I'll post your ads all over this page, I'll scream your name from my rooftop, I'll wear your shirts, I'll put bumper stickers on my car... Anything! And for those of you who live in areas with a steady supply of Diet Mountain Dew, please help a brother out :). If you think I'm joking, I'm not.  my phone:&lt;br /&gt;&lt;br /&gt;505-991-0973 (or call my room-mate: 505-991-1143)&lt;br /&gt;&lt;br /&gt;and my e-mail:&lt;br /&gt;&lt;br /&gt;james [at] tweekedideas [dot] com&lt;br /&gt;&lt;br /&gt;Thank you all for your support! Good night, and good luck, James.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;Update: (Jul 29, 2006)&lt;/b&gt; stores are stocked :) Thank you, The Pepsi Corporation. The offer for sponsorship still stands.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115386194995337354?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115386194995337354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115386194995337354' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115386194995337354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115386194995337354'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/07/diet-mountain-dew-where-art-thou.html' title='Diet Mountain Dew, Where Art Thou?'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115306991058627386</id><published>2006-07-16T10:10:00.000-07:00</published><updated>2006-11-15T21:19:54.195-07:00</updated><title type='text'>No whirlpool for python... Not anymore :)</title><content type='html'>I just finished writing a c extension module for python so you can finally&lt;br /&gt;use whirlpool with python. There might have been one already, but I sure couldn't&lt;br /&gt;find it. This pretty much just wraps the C whirlpool implementation on the main site.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://kepty.com/items/4_Whirlpool_implementation_for_python" title="pyWhirlpool"&gt;&lt;br /&gt;Whirlpool for Python&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I put it up on Kepty just to show something about why kepty is good, and to make&lt;br /&gt;myself feel better about the service that GETS NO VISITORS! (Just hope it doesn't&lt;br /&gt;crash before you head over there to grab the file).&lt;br /&gt;&lt;br /&gt;Good day everyone,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115306991058627386?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115306991058627386/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115306991058627386' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115306991058627386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115306991058627386'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/07/no-whirlpool-for-python-not-anymore.html' title='No whirlpool for python... Not anymore :)'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115250120807185042</id><published>2006-07-09T20:03:00.000-07:00</published><updated>2006-11-15T21:19:54.092-07:00</updated><title type='text'>Creating a torrent site</title><content type='html'>Hey everyone,&lt;br /&gt;&lt;br /&gt;If you've known me at all you know that something I truly desire to do is create a unique torrent site... What's been stopping me? Legality. It's a gray area, and I'd hate for my business to suffer because I broke a law I didn't even know about. &lt;br /&gt;&lt;br /&gt;For the past few months I've been trying to figure out how to create a legal torrent site, and do it without fear of lawsuit. Last night I got fed up with the fear and decided to let the RIAA answer my question for me... "Can I create a torrent site? What do I have to fear?"&lt;br /&gt;&lt;br /&gt;The answer became clear while I was writing the following e-mail... If the RIAA wants to cut down on piracy, why not offer a fucking way to help us developers do what they want? Torrent sites get thousands and thousands of torrents a day, and sifting through them for legal purposes can be a mind-numbing and unrewarding task. 1) Here's the e-mail: &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Dear Record Industry Association of America,&lt;br /&gt;&lt;br /&gt;I'm looking to add torrent file distribution features to a site of mine, and, since you're the entity who is (arguably) the one most concerned with the distribution of torrent files I'm writing to ask you what features you would like to see in such a site that would make you more comfortable with its existence.&lt;br /&gt;&lt;br /&gt;Perhaps I should stress that this feature will be designed for the distribution of LEGAL torrents, such as linux distributions and copyright-free music, but since my plans are for this to be community-based it MAY be possible for a user to upload a copyrighted piece. Is there some sort of API that you would like this to be programmed with that would allow you to notify me when a file is suspicious or illegal? If not, may I recommend the creation of one? Perhaps allow programmers to check a database against hashes of files that you consider copyrighted? There are many developers out there who would be more than willing to add such compatiblity to their site to avoid lawsuit. I'd even be willing to create such a service if you were to participate in keeping the database up to date.&lt;br /&gt;&lt;br /&gt;In any case I look forward to your response and I thank you for your time.&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;And here's a little more detailed idea of what I'm proposing:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;User uploads torrent file.&lt;/li&gt;&lt;li&gt;Torrent file is hashed (md5 or something faster)...&lt;/li&gt;&lt;li&gt;Torrent site contacts riaa/mpaa api with the hash.&lt;/li&gt;&lt;li&gt;API returns a rating on the scale of 0 to 10, 0 being no risk, 10 being high risk.&lt;/li&gt;&lt;li&gt;The torrent site can make the CHOICE whether or not to make the file public, but a proper implementation would allow the owner of the site to review high risk items before making them available to the general public (abuse by mpaa or riaa would be limited by this).&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;This solves all their problems! No change to their business model, no profit problems, nothing! All it requires is a little work to put the system up (which I've even offered to do FOR THEM), and maybe a few man-hours checking on torrents (which they do already, anyway). &lt;br /&gt;&lt;br /&gt;So, the next time the RIAA or MPAA tells you that piracy is making a huge dent in their profits, tell them that they DO have the power to do something about it, and that they start evolving and stop whining.&lt;br /&gt;&lt;br /&gt;Talk to you later,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115250120807185042?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115250120807185042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115250120807185042' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115250120807185042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115250120807185042'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/07/creating-torrent-site.html' title='Creating a torrent site'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115191957638060780</id><published>2006-07-03T02:37:00.000-07:00</published><updated>2006-11-15T21:19:54.001-07:00</updated><title type='text'>Next Project</title><content type='html'>Just thought I'd keep my blog up to date with what I'm working on. Here's a teaser:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/screenshot.4.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/screenshot.4.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Yeah, but it's not a clone of what you're thinking... It's MUCH more than that. Stay tuned to see a) if it works out, and b) to see what's so great about it.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update: The project is Kepty. It's online now: &lt;a href="http://www.kepty.com"&gt;Kepty&lt;/a&gt;&lt;/b&gt;.&lt;br /&gt;-James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115191957638060780?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115191957638060780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115191957638060780' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115191957638060780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115191957638060780'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/07/next-project.html' title='Next Project'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115117779985614666</id><published>2006-06-24T12:32:00.000-07:00</published><updated>2006-11-15T21:19:53.913-07:00</updated><title type='text'>Farey Sequence Python Implementation</title><content type='html'>I looked this up a little earlier today, and wasn't finding anything that would give me a simple &lt;a href="http://mathworld.wolfram.com/FareySequence.html"&gt;farey sequence&lt;/a&gt; with python. Figured I may as well post what I wrote that I'm about to stick up in the python cookbook.&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;def farey(n):&lt;br /&gt;    def gcd(a,b):&lt;br /&gt;        while b: a,b = b,a%b&lt;br /&gt;        return a&lt;br /&gt;&lt;br /&gt;    def simplify(a,b):&lt;br /&gt;        g = gcd(a,b)&lt;br /&gt;        return (a/g,b/g)&lt;br /&gt;&lt;br /&gt;    fs = dict()&lt;br /&gt;    for i in xrange(1,n+1):&lt;br /&gt;        for i2 in xrange(1,i+1):&lt;br /&gt;            if i2 &lt; n and i != i2:&lt;br /&gt;                r = simplify(i2,i)&lt;br /&gt;                fs[float(i2)/i] = r&lt;br /&gt;&lt;br /&gt;    return [fs[k] for k in sorted(fs.keys())]&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It neglects the (0,1) and (1,1) because they're obvious enough and I &lt;br /&gt;end up removing them in my code anyway. Somebody out there can probably&lt;br /&gt;figure out a more efficient and elegant solution, but this is pretty&lt;br /&gt;quick and works just fine.&lt;br /&gt;&lt;br /&gt;Take it easy,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115117779985614666?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115117779985614666/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115117779985614666' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115117779985614666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115117779985614666'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/06/farey-sequence-python-implementation.html' title='Farey Sequence Python Implementation'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115099424712871432</id><published>2006-06-22T09:37:00.000-07:00</published><updated>2006-11-15T21:19:53.802-07:00</updated><title type='text'>Killing Internet Explorer</title><content type='html'>As developers we love to reuse our once-written code. As graphic designers we love to keep things simple.  As the local "computer guy" we love it when we don't have to spend long, boring hours in front of a Windows installation progress bar in an attempt to remove trojans and adware from our friend's computers. And it's for this horribly unnecessary waste of time and effort - not any of the million less selfish reasons we've given those around us - we hate Microsoft Internet Explorer. Stop complaining about greedy bundling practices that are never going to change... We have the power to kill this beast, and we can do it now.&lt;br /&gt;&lt;br /&gt;Ah. You're in vim (unarguably the best editor of all time) designing your latest web masterpiece. You're constantly switching between your editor and the Firefox window you've got open hitting "refresh" endlessly. Your fingers are stiff, your eyes dry and scratchy, your Mountain Dew 2-Liter nearly through, and you're almost done. It's absolutely beautiful. Perfect... Your client's going to want to spend those big bucks now, and this is a great piece to add to your portfolio. You've just got to open up IE, and BAM! Your CSS float didn't display as it should have and you're going to have to spend another hour editing your design to make it work... Wouldn't it be MUCH simpler to just say screw everybody who didn't have the correct browser? The answer is yes. It would. And that's what I'm going to suggest you do.&lt;br /&gt;&lt;br /&gt;Case in point. &lt;a href="http://www.matchstd.com"&gt;MatchSTD.com&lt;/a&gt;, my latest project. Chat room access is only provided to individuals who are using a browser OTHER than Internet Explorer. If you're browsing with Internet Explorer you can get every page on the site, except the chat room:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/nochatforyou.0.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/nochatforyou.0.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Any other browser (Firefox, here):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/chatforyou.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/chatforyou.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Users are informed why Internet Explorer is bad for them, and then are forced to download and use another browser if they want access to the page. It's worked well so far. The majority of users will either download install and launch a new browser, or simply switch to an already installed Firefox and access the page. The problem with this? They'll switch right back to IE because there's no reason, except when browsing this specific site, that they'd want to use Firefox instead. A normal computer user isn't going to have concerns over spyware, viruses, print-abort-proc remote code injection vulnerabilities, and the like. They'll care whether or not they can do what they aimed to do when the logged on. So why is IE not threatened by Firefox? Because we're supporting them fully. So how do we go about doing this?&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt; &lt;li&gt;&lt;b&gt;Examine your site by feature&lt;/b&gt;&lt;br /&gt;  &lt;p&gt;Take a look at your site. List every specific, independent feature that you've programmed. Find a feature that's useful, fun, and &lt;i&gt;not necessary for site function&lt;/i&gt;.&lt;/p&gt;&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;b&gt;Block Internet Explorer User-Agent Headers Access&lt;/b&gt;&lt;br /&gt;  &lt;p&gt;If the user agent contains MSIE. Stop it.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;You're thinking, "But James, that's really easy to spoof. I change it all the time to try to access IE-only sites!" And you are absolutely right. We're not attempting to convert users who have demonstrated such motivation, we're trying to convert the masses... And let's face it, the majority of the audience for most sites will follow the instructions that are in front of them because no desire to research instructions on something they don't even know how to google for.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;The most important thing about this is that you're not blocking users from your site. You are just visibly making their internet experience more pleasurable, as they will do for you by using another browser. Make sure you provide different links for getting firefox. Try &lt;a href="http://www.spreadfirefox.com"&gt;spreadfirefox.com&lt;/a&gt; for images and ideas. Join their affiliate program and watch your conversions grow :)&lt;/p&gt;&lt;br /&gt; &lt;li&gt;&lt;b&gt;Let others know&lt;/b&gt;&lt;br /&gt;  &lt;p&gt;If other webmasters begin using this technique, users will be less inclined to switch back to Internet Explorer after they're done on your page. &lt;i&gt;And it doesn't take the participation of a big site!&lt;/i&gt; A typical user will visit hundreds (perhaps thousands) of pages while browsing the internet. If a larger number of sites that offer Non-IE only content in relation to the number of sites that block users not using IE exist on the internet, users will be forced to switch from Firefox to Internet Explorer, generating a dislike for the latter.&lt;/p&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;If you don't have a website of your own, start making requests to other sites to block sections of content from users on Internet Explorer.  Explain to them the benefits. As previously stated, It doesn't take the participation of larger sites, simply the participation of many smaller ones. Spread the word, and maybe we can start living easier without IE!&lt;br /&gt;&lt;br /&gt;Take it easy, and thank you!&lt;br /&gt;&lt;br /&gt;James Kassemi&lt;br /&gt;james at tweekedideas dot com&lt;br /&gt;james at matchstd dot com&lt;br /&gt;505-991-0973&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115099424712871432?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115099424712871432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115099424712871432' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115099424712871432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115099424712871432'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/06/killing-internet-explorer.html' title='Killing Internet Explorer'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-115054874807715987</id><published>2006-06-17T05:46:00.000-07:00</published><updated>2006-11-15T21:19:53.707-07:00</updated><title type='text'>captchas are too much fun</title><content type='html'>Hey everyone, I've been writing a bit of code at ASPN's Python Cookbook... I figure when I come across something nice for others to know I'll put it somewhere that gets a bit more traffic. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496787"&gt;HTML Div parser&lt;/a&gt;&lt;br /&gt;&lt;a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496800"&gt;Event Scheduler&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I was using a more complicated event scheduler, and decided I wanted to simplify it a bit, so that's the product of that. I also can't really avoid the captcha draw, so I started working on a new algorithm just in case people start breaking my old images (which hasn't happened yet, but wouldn't be all that hard). Here's a screenshot:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/screenshot.3.jpg"&gt;&lt;img style="margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/screenshot.3.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;br/&gt;&lt;br /&gt;I'm using psyco because without it they're just too slow, but I've got optimization plans... I'm also going to add either some sort of disguising line, or a randomly shifted grid. I'll run some AI tests against them to see what the best idea would be. Plans to incorporate different colors also exist, but let's be honest: if a system is designed well enough, spammers won't matter to the users, and in the end, if your system can't handle the load placed on it by spammers, it shouldn't be up in the first place, so my fascination with these things is admittedly unfounded. &lt;br /&gt;&lt;br /&gt;Have a good one!&lt;br /&gt;&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-115054874807715987?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/115054874807715987/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=115054874807715987' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115054874807715987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/115054874807715987'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/06/captchas-are-too-much-fun.html' title='captchas are too much fun'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-114968328431786132</id><published>2006-06-07T05:26:00.000-07:00</published><updated>2006-11-15T21:19:51.356-07:00</updated><title type='text'>Quck server part 2</title><content type='html'>Just decided I'd keep on updating my progress on this one.&lt;br /&gt;Dump it on top of cherrypy for a quick, dirty little server for simpler requests.&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;'''&lt;br /&gt;A BASIC server to embed inside another for simple, fast operations&lt;br /&gt;Copyright (C) 2006 James Kassemi (Tweeked Ideas)&lt;br /&gt;&lt;br /&gt;This library is free software; you can redistribute it and/or&lt;br /&gt;modify it under the terms of the GNU Lesser General Public&lt;br /&gt;License as published by the Free Software Foundation; either&lt;br /&gt;version 2.1 of the License, or (at your option) any later version.&lt;br /&gt;&lt;br /&gt;This library is distributed in the hope that it will be useful,&lt;br /&gt;but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU&lt;br /&gt;Lesser General Public License for more details.&lt;br /&gt;&lt;br /&gt;You should have received a copy of the GNU Lesser General Public&lt;br /&gt;License along with this library; if not, write to the Free Software&lt;br /&gt;Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA&lt;br /&gt;&lt;br /&gt;_________________________________________________________________&lt;br /&gt;&lt;br /&gt;You'll have to bind this to a different port to handle the requests. If you&lt;br /&gt;don't want to deal with apparent port differences in your code, simply&lt;br /&gt;use a rewrite rule in your apache configuration, much like you do to redirect&lt;br /&gt;cherrypy requests in a production environment.&lt;br /&gt;&lt;br /&gt;Also, there are different types of request classes available here for you&lt;br /&gt;to play around with... If you use the Request_Quick_CPSession class you&lt;br /&gt;will be able to piggy-back the cherrypy session id generator to create&lt;br /&gt;some simple sessions. I've got a database session class in cherrypy that&lt;br /&gt;I also have wrapped around a request class for this, which allows manipulations&lt;br /&gt;of the session from here... eh, obvious. Have fun!&lt;br /&gt;&lt;br /&gt;'''&lt;br /&gt;&lt;br /&gt;import socket&lt;br /&gt;import thread&lt;br /&gt;import threading&lt;br /&gt;import Queue&lt;br /&gt;import urlparse&lt;br /&gt;import time&lt;br /&gt;import traceback&lt;br /&gt;&lt;br /&gt;# Straight from cherrypy&lt;br /&gt;import errno&lt;br /&gt;socket_errors_to_ignore = []&lt;br /&gt;for _ in ("EPIPE", "ETIMEDOUT", "ECONNREFUSED", "ECONNRESET",&lt;br /&gt;          "EHOSTDOWN", "EHOSTUNREACH",&lt;br /&gt;          "WSAECONNABORTED", "WSAECONNREFUSED", "WSAECONNRESET",&lt;br /&gt;          "WSAENETRESET", "WSAETIMEDOUT"):&lt;br /&gt;    if _ in dir(errno):&lt;br /&gt;        socket_errors_to_ignore.append(getattr(errno, _))&lt;br /&gt;socket_errors_to_ignore = dict.fromkeys(socket_errors_to_ignore).keys()&lt;br /&gt;# End&lt;br /&gt;&lt;br /&gt;WORKER_COUNT = 50&lt;br /&gt;SOCKET_QUEUE = 10&lt;br /&gt;&lt;br /&gt;TIMEOUT = 10&lt;br /&gt;&lt;br /&gt;_SHUTDOWN = 1&lt;br /&gt;STATUS_CODES = {&lt;br /&gt;        200: 'OK',&lt;br /&gt;        404: 'Not Found',&lt;br /&gt;        500: 'Internal Error'&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;request = threading.local()&lt;br /&gt;info = threading.local()&lt;br /&gt;session = threading.local()&lt;br /&gt;&lt;br /&gt;start_thread = []&lt;br /&gt;stop_thread = []&lt;br /&gt;start_request = []&lt;br /&gt;stop_request = []&lt;br /&gt;&lt;br /&gt;SESSION_DATA = dict()&lt;br /&gt;&lt;br /&gt;class Session(dict):&lt;br /&gt;    def __init__(self, id):&lt;br /&gt;        self.id = id&lt;br /&gt;        try:&lt;br /&gt;            self.update(SESSION_DATA[id])&lt;br /&gt;        except: pass&lt;br /&gt;        self['_id'] = id&lt;br /&gt;&lt;br /&gt;    def _save(self):&lt;br /&gt;        SESSION_DATA[self.id] = dict()&lt;br /&gt;        SESSION_DATA[self.id].update(self)&lt;br /&gt;&lt;br /&gt;class Request:&lt;br /&gt;    ''' Request processing. '''&lt;br /&gt;&lt;br /&gt;    def __init__(self, socket):&lt;br /&gt;        for item in start_request:&lt;br /&gt;            item(self)&lt;br /&gt;        self.socket = socket&lt;br /&gt;        self.rfile = self.socket.makefile("r", -1)&lt;br /&gt;        self.wfile = self.socket.makefile("w", -1)&lt;br /&gt;        self.header_temp = ''&lt;br /&gt;&lt;br /&gt;    def end_headers(self):&lt;br /&gt;        self.wfile.write(self.header_temp)&lt;br /&gt;        self.wfile.write('\r\n')&lt;br /&gt;        self.header_temp = ''&lt;br /&gt;&lt;br /&gt;    def send_header(self, name, value):&lt;br /&gt;        self.header_temp += '%s: %s\r\n' % (name, value)&lt;br /&gt;&lt;br /&gt;    def send_response(self, code):&lt;br /&gt;        self.header_temp = 'HTTP/1.1 %i %s\r\n' % (code, STATUS_CODES[code])&lt;br /&gt;&lt;br /&gt;    def path_process(self):&lt;br /&gt;        path = self.request_line.split(' ')[1]&lt;br /&gt;        parsed = urlparse.urlparse(path)&lt;br /&gt;        path = parsed[2]&lt;br /&gt;        args = parsed[4]&lt;br /&gt;        args = args.replace(';', '&amp;')&lt;br /&gt;        arg_dict = dict()&lt;br /&gt;        try:&lt;br /&gt;            args = [arg_dict.update({item[0]:item[1]}) for item in [arg.split('=') for arg in args.split('&amp;')]]&lt;br /&gt;        except: pass&lt;br /&gt;        try:&lt;br /&gt;            path = path[1:].split('/')&lt;br /&gt;            return getattr(apps[path[0]], path[1], False)(**arg_dict)&lt;br /&gt;        except: return False&lt;br /&gt;&lt;br /&gt;    def respond(self, code, ctype, content):&lt;br /&gt;        self.send_response(code)&lt;br /&gt;        self.send_header('Server', 'TweekedIdeas/1.0')&lt;br /&gt;        self.send_header('Content-Type', ctype)&lt;br /&gt;        self.end_headers()&lt;br /&gt;        for line in content:&lt;br /&gt;            self.wfile.write(line)&lt;br /&gt;        self.wfile.flush()&lt;br /&gt;&lt;br /&gt;    def process(self):&lt;br /&gt;        self.request_line = self.rfile.readline()&lt;br /&gt;        self.request_headers = dict()&lt;br /&gt;        while True:&lt;br /&gt;            header = self.rfile.readline()&lt;br /&gt;            if header.strip() == '': break&lt;br /&gt;            dl = header.find(':')&lt;br /&gt;            self.request_headers[header[0:dl]]=header[dl+2:].rstrip()&lt;br /&gt;        request.headers = self.request_headers&lt;br /&gt;        try:&lt;br /&gt;            res = self.path_process()&lt;br /&gt;        except Exception, e:&lt;br /&gt;            e2 = traceback.format_exc()&lt;br /&gt;            print e2&lt;br /&gt;            self.respond(500, 'text/plain', 'Internal Server Error\n\n%s' % e2)&lt;br /&gt;            return&lt;br /&gt;        if res:&lt;br /&gt;            self.respond(200, 'text/html', res)&lt;br /&gt;        else:&lt;br /&gt;            self.respond(404, 'text/html', 'Not Found')&lt;br /&gt;&lt;br /&gt;    def destroy(self):&lt;br /&gt;        self.socket.close()&lt;br /&gt;        self.wfile.close()&lt;br /&gt;        self.rfile.close()&lt;br /&gt;        for item in stop_request:&lt;br /&gt;            item(self)&lt;br /&gt;&lt;br /&gt;class Request_Advanced(Request):&lt;br /&gt;    def path_process(self):&lt;br /&gt;        # Allows for generators and more complex layout.&lt;br /&gt;        path = self.request_line.split(' ')[1]&lt;br /&gt;        parsed = urlparse.urlparse(path)&lt;br /&gt;        path = parsed[2]&lt;br /&gt;        args = parsed[4]&lt;br /&gt;        args = args.replace(';', '&amp;')&lt;br /&gt;        arg_dict = dict()&lt;br /&gt;        try:&lt;br /&gt;            args = [arg_dict.update({item[0]:item[1]}) for item in [arg.split('=') for arg in args.split('&amp;')]]&lt;br /&gt;        except: arg_dict = dict()&lt;br /&gt;        try:&lt;br /&gt;            path = path[1:].split('/')&lt;br /&gt;            focus = app&lt;br /&gt;            for part in path:&lt;br /&gt;                focus = getattr(focus, part, False)&lt;br /&gt;                if not focus: return False&lt;br /&gt;            ret_val = focus(**arg_dict)&lt;br /&gt;            ret_val_type = type(ret_val)&lt;br /&gt;            if type(ret_val) == tuple:&lt;br /&gt;                from Cheetah.Template import Template&lt;br /&gt;                t = Template.compile(file=ret_val[0])()&lt;br /&gt;                data = str(t)&lt;br /&gt;                #data = _render(ret_val[1], ret_val[0], 'cheetah', focus)&lt;br /&gt;                print '...', data&lt;br /&gt;                return data&lt;br /&gt;            return ret_val&lt;br /&gt;        except: traceback.print_exc()&lt;br /&gt;        return False&lt;br /&gt;&lt;br /&gt;class Request_Quick(Request):&lt;br /&gt;    def path_process(self):&lt;br /&gt;        global apps&lt;br /&gt;        path = self.request_line.split(' ')[1]&lt;br /&gt;        parsed = urlparse.urlparse(path)&lt;br /&gt;        path = parsed[2][1:]&lt;br /&gt;        args = parsed[4]&lt;br /&gt;        arg_dict = dict()&lt;br /&gt;        try:&lt;br /&gt;            args = [arg_dict.update({item[0]:item[1]}) for item in [arg.split('=') for arg in args.split('&amp;')]]&lt;br /&gt;        except: arg_dict = dict()&lt;br /&gt;        focus = apps.get(path, False)&lt;br /&gt;        if not focus: return False&lt;br /&gt;        return focus(**arg_dict)&lt;br /&gt;&lt;br /&gt;class Request_Quick_CPSession(Request):&lt;br /&gt;    def path_process(self):&lt;br /&gt;        global apps&lt;br /&gt;        c = info.cookie&lt;br /&gt;        try:&lt;br /&gt;            c.load(request.headers['Cookie'])&lt;br /&gt;            info.session = Session(c['session_id'].value)&lt;br /&gt;        except KeyError:&lt;br /&gt;            info.session = dict()&lt;br /&gt;&lt;br /&gt;        path = self.request_line.split(' ')[1]&lt;br /&gt;        parsed = urlparse.urlparse(path)&lt;br /&gt;        path = parsed[2][1:]&lt;br /&gt;        args = parsed[4]&lt;br /&gt;        arg_dict = dict()&lt;br /&gt;        try:&lt;br /&gt;            args = [arg_dict.update({item[0]:item[1]}) for item in [arg.split('=') for arg in args.split('&amp;')]]&lt;br /&gt;        except: arg_dict = dict()&lt;br /&gt;        focus = apps.get(path, False)&lt;br /&gt;        if not focus: return False&lt;br /&gt;        ret = focus(**arg_dict)&lt;br /&gt;        info.session._save()&lt;br /&gt;        return ret&lt;br /&gt;&lt;br /&gt;class Worker(threading.Thread):&lt;br /&gt;    ''' Sits around and handles requests as they appear. '''&lt;br /&gt;&lt;br /&gt;    def __init__(self, server):&lt;br /&gt;        self.server = server&lt;br /&gt;        self.ready = False&lt;br /&gt;        self.go = True&lt;br /&gt;        threading.Thread.__init__(self)&lt;br /&gt;&lt;br /&gt;    def run(self):&lt;br /&gt;        for item in start_thread:&lt;br /&gt;            item(self)&lt;br /&gt;        while self.go:&lt;br /&gt;            self.ready = True&lt;br /&gt;            request = self.server.request_pool.get()&lt;br /&gt;            if request == _SHUTDOWN:&lt;br /&gt;                self.ready=False&lt;br /&gt;                for item in stop_thread:&lt;br /&gt;                    item(self)&lt;br /&gt;                return&lt;br /&gt;            try:&lt;br /&gt;                try:&lt;br /&gt;                    request.process()&lt;br /&gt;                except socket.error, e:&lt;br /&gt;                    errno = e.args[0]&lt;br /&gt;                    if errno not in socket_errors_to_ignore:&lt;br /&gt;                        traceback.print_exc()&lt;br /&gt;                except:&lt;br /&gt;                    traceback.print_exc()&lt;br /&gt;                    return&lt;br /&gt;            finally:&lt;br /&gt;                request.destroy()&lt;br /&gt;&lt;br /&gt;    def stop(self):&lt;br /&gt;        self.go = False&lt;br /&gt;&lt;br /&gt;class Server:&lt;br /&gt;    ''' Grabs incoming connections and pools them. '''&lt;br /&gt;&lt;br /&gt;    def __init__(self, host='', port=8080, thread_count=10, socket_queue=5, request_class=Request):&lt;br /&gt;        self.host = host&lt;br /&gt;        self.port = port&lt;br /&gt;        WORKER_COUNT = thread_count&lt;br /&gt;        SOCKET_QUEUE = socket_queue&lt;br /&gt;        self.request_class = request_class&lt;br /&gt;        self.request_pool = Queue.Queue(-1)&lt;br /&gt;        self.workers = []&lt;br /&gt;        self.stop_flag = False&lt;br /&gt;&lt;br /&gt;    def start(self):&lt;br /&gt;        addr = (self.host, self.port)&lt;br /&gt;&lt;br /&gt;        import os&lt;br /&gt;        self.socket = socket.socket()&lt;br /&gt;        try: os.unlink(addr)&lt;br /&gt;        except: pass&lt;br /&gt;        try: os.chmod(addr, 0777)&lt;br /&gt;        except: pass&lt;br /&gt;        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)&lt;br /&gt;        time.sleep(.1)&lt;br /&gt;        self.socket.bind(addr)&lt;br /&gt;        self.socket.listen(SOCKET_QUEUE)&lt;br /&gt;        for i in xrange(WORKER_COUNT):&lt;br /&gt;            self.workers.append(Worker(self))&lt;br /&gt;        for worker in self.workers:&lt;br /&gt;            worker.start()&lt;br /&gt;            while not worker.ready:&lt;br /&gt;                time.sleep(.1)&lt;br /&gt;        while not self.stop_flag:&lt;br /&gt;            s, addr = self.socket.accept()&lt;br /&gt;            s.settimeout(TIMEOUT)&lt;br /&gt;            self.request_pool.put(self.request_class(s), False)&lt;br /&gt;&lt;br /&gt;    def stop(self):&lt;br /&gt;        self.stop_flag = True&lt;br /&gt;        print "Shutting down AJAX server."&lt;br /&gt;        for worker in self.workers:&lt;br /&gt;            self.request_pool.put(_SHUTDOWN)&lt;br /&gt;        for worker in self.workers:&lt;br /&gt;            worker.stop&lt;br /&gt;            time.sleep(.05)&lt;br /&gt;        while True:&lt;br /&gt;            try:&lt;br /&gt;                del self.workers[0]&lt;br /&gt;            except: break&lt;br /&gt;        print "Done"&lt;br /&gt;&lt;br /&gt;apps = dict()&lt;br /&gt;&lt;br /&gt;def mount(app, name):&lt;br /&gt;    global apps&lt;br /&gt;    apps[name] = app&lt;br /&gt;&lt;br /&gt;server = None&lt;br /&gt;&lt;br /&gt;def start(host='', port=8080, threads=10, squeue=5, catch=False):&lt;br /&gt;    global server&lt;br /&gt;    server = Server(host=host, port=port, thread_count=threads,&lt;br /&gt;            socket_queue=squeue, request_class=Request_Quick_CPSession)&lt;br /&gt;&lt;br /&gt;    print "AJAX server started on %s:%i." % (host, port)&lt;br /&gt;&lt;br /&gt;    thread.start_new_thread(server.start, ())&lt;br /&gt;&lt;br /&gt;    if catch:&lt;br /&gt;        try:&lt;br /&gt;            while True:&lt;br /&gt;                time.sleep(3)&lt;br /&gt;        except:&lt;br /&gt;            server.stop()&lt;br /&gt;            server.socket.close()&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-114968328431786132?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/114968328431786132/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=114968328431786132' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114968328431786132'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114968328431786132'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/06/quck-server-part-2.html' title='Quck server part 2'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-114951865510736363</id><published>2006-06-05T07:27:00.000-07:00</published><updated>2006-11-15T21:19:51.255-07:00</updated><title type='text'>A very quick little http server</title><content type='html'>I've been working on an AJAX chat room, and I'm trying my best to fine tune it&lt;br /&gt;for system resources. As you know, I use cherrypy frequently, and it's a great&lt;br /&gt;server, but for something as simple as a setInterval poll that just checks&lt;br /&gt;for messages, it's not worth it to have all that extra processing involved. In&lt;br /&gt;fact, it's not even necessary to have something standards compliant... That's&lt;br /&gt;why I decided to write a very simple little web server that can be used within&lt;br /&gt;cherrypy by binding it to another port and mounting a very small application. &lt;br /&gt;&lt;br /&gt;The application won't be searched any more than one level, and like I said, there&lt;br /&gt;isn't any support for HTTP standards... It just fires off as many pages per second that&lt;br /&gt;it can (ab -n 10000 http://127.0.0.1:8080/hello/world =&gt; 2236.12 #/sec). This compares with a simple CherryPy server on my machine running approx 350 #/sec... Yeah, my machine isn't that great, but it just leads you into finding ways to optimize more than you would ever think.&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;import SocketServer&lt;br /&gt;import urlparse&lt;br /&gt;&lt;br /&gt;STATUS_CODES = {&lt;br /&gt;        200: 'OK',&lt;br /&gt;        404: 'Not Found',&lt;br /&gt;        500: 'Internal Error'}&lt;br /&gt;&lt;br /&gt;class Handler(SocketServer.StreamRequestHandler):&lt;br /&gt;    header_temp = ''&lt;br /&gt;&lt;br /&gt;    def end_headers(self):&lt;br /&gt;        self.wfile.write(self.header_temp)&lt;br /&gt;        self.wfile.write('\r\n')&lt;br /&gt;        self.wfile.flush()&lt;br /&gt;        self.header_temp = ''&lt;br /&gt;&lt;br /&gt;    def send_header(self, name, value):&lt;br /&gt;        self.header_temp += '%s: %s\r\n' % (name, value)&lt;br /&gt;&lt;br /&gt;    def send_response(self, code):&lt;br /&gt;        self.header_temp = 'HTTP/1.1 %i %s\r\n' % (code, STATUS_CODES[code])&lt;br /&gt;&lt;br /&gt;    def respond(self, code, ctype, content):&lt;br /&gt;        self.send_response(code)&lt;br /&gt;        self.send_header('Server', 'TI/1.0')&lt;br /&gt;        self.send_header('Content-Type', ctype)&lt;br /&gt;        self.end_headers()&lt;br /&gt;        self.wfile.write(content)&lt;br /&gt;&lt;br /&gt;    def path_process(self):&lt;br /&gt;        path = self.request_line.split(' ')[1]&lt;br /&gt;        parsed = urlparse.urlparse(path)&lt;br /&gt;        path = parsed[2]&lt;br /&gt;        args = parsed[4]&lt;br /&gt;        args = args.replace(';', '&amp;')&lt;br /&gt;        arg_dict = dict()&lt;br /&gt;        try:&lt;br /&gt;            args = [arg_dict.update({item[0]:item[1]}) for item in [arg.split('=') for arg in args.split('&amp;')]]&lt;br /&gt;        except: pass&lt;br /&gt;        try:&lt;br /&gt;            path = path[1:].split('/')&lt;br /&gt;            return getattr(apps[path[0]], path[1], False)(**arg_dict)&lt;br /&gt;        except: return False&lt;br /&gt;&lt;br /&gt;    def handle(self):&lt;br /&gt;        self.request_line = self.rfile.readline()&lt;br /&gt;        try:&lt;br /&gt;            res = self.path_process()&lt;br /&gt;        except Exception, e:&lt;br /&gt;            self.respond(500, 'text/html', 'Internal Server Error&lt;br/&gt;%s' % e)&lt;br /&gt;            return&lt;br /&gt;        if res:&lt;br /&gt;            self.respond(200, 'text/html', res)&lt;br /&gt;        else:&lt;br /&gt;            self.respond(404, 'text/html', 'Not Found')&lt;br /&gt;&lt;br /&gt;class Server(SocketServer.TCPServer): pass&lt;br /&gt;class ServerThreaded(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass&lt;br /&gt;&lt;br /&gt;apps = dict()&lt;br /&gt;def mount(app, name):&lt;br /&gt;    global apps&lt;br /&gt;    apps[name] = app&lt;br /&gt;&lt;br /&gt;def start(host='', port=8080, threaded=False):&lt;br /&gt;    if not threaded:&lt;br /&gt;        server = Server((host, port), Handler)&lt;br /&gt;    else:&lt;br /&gt;        server = ServerThreaded((host, port), Handler)&lt;br /&gt;    server.serve_forever()&lt;br /&gt;&lt;br /&gt;# The sample application:&lt;br /&gt;&lt;br /&gt;class Application:&lt;br /&gt;    def world(self, *args, **kwargs):&lt;br /&gt;        # /hello/world&lt;br /&gt;        return 'Hey there!'&lt;br /&gt;&lt;br /&gt;    def error(self, **kwargs):&lt;br /&gt;        # /hello/error&lt;br /&gt;        a = 1/0&lt;br /&gt;        return 'Error!'&lt;br /&gt;&lt;br /&gt;if __name__ == '__main__':&lt;br /&gt;    a = Application()&lt;br /&gt;    mount(a, 'hello')&lt;br /&gt;    start(port=5558)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;As always, have fun.... And you people should start making some comments, assuming you're reading... Maybe I should get a counter up on here....&lt;br /&gt;&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-114951865510736363?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/114951865510736363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=114951865510736363' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114951865510736363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114951865510736363'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/06/very-quick-little-http-server.html' title='A very quick little http server'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-114518745126940632</id><published>2006-04-16T04:30:00.000-07:00</published><updated>2006-11-15T21:19:51.158-07:00</updated><title type='text'>Python based full-text search for postgresql...</title><content type='html'>Hey everyone. I'm back... I've just been too busy, and have thus ignored this blog. But, I have a good present for you today, a very simple relevance-based full-text search engine for your python based programs... If you've looked into tsearch2, but are on a hosting provider that might not let you install it, you've had to go looking around (or program one, if you're like me). The stemmer module is not something I wrote. All credits are located in the stemmer module's source.&lt;br /&gt;&lt;br /&gt;Here's the source for this one:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.matchstd.com/static/search.tar.gz"&gt;search.tar.gz&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update: For best results, modify the frequency ranking to rank less over time for many multiple mentions of a term... The way I'm using is a simple 1/x^2 scale. This will prevent some issues with abuse my repetition of a term again and again, but you might want to try hitting up sort of limiting logarithmic function or something along those lines to be just a bit more careful.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Let's say you have a forum that you'd like to search with a post table similar to the following:&lt;br /&gt;&lt;br /&gt;id | content # Name: forum_posts&lt;br /&gt;&lt;br /&gt;That oversimplifies it, but anyway...&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;#populate the search database&lt;br /&gt;import search&lt;br /&gt;search.populate('forum_posts', 'id', 'content')&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So you've populated with the posts that you've already got. Now when you want to add another post:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;# Add two posts, id 1034 and 1035 with the text specified.&lt;br /&gt;import search&lt;br /&gt;search.add(1034, 'This is functional, I hope.')&lt;br /&gt;search.add(1035, 'This as well, maybe.')&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And when you want to search the database for a post:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;import search&lt;br /&gt;res = search.search('functional')&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Which will return a list ordered by relevance desc of the post ids that match&lt;br /&gt;the search... There are no boolean-type searches, etc... Everything is done via a simple (incomplete but functional) relevance function... You can edit it if you'd like. It works now, but I plan to tweak it in the future.&lt;br /&gt;&lt;br /&gt;Anyway, have fun!&lt;br /&gt;&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-114518745126940632?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.matchstd.com/static/search.tar.gz' title='Python based full-text search for postgresql...'/><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/114518745126940632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=114518745126940632' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114518745126940632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114518745126940632'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/04/python-based-full-text-search-for.html' title='Python based full-text search for postgresql...'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-114398755013168701</id><published>2006-04-02T07:10:00.000-07:00</published><updated>2006-11-15T21:19:51.072-07:00</updated><title type='text'>Matchstd.com Hits CNN!</title><content type='html'>Hello everyone,&lt;br /&gt;&lt;br /&gt;My first big site ever, http://www.matchstd.com, has made CNN headline news this morning... It's great to see that happen... I only wish that I had been informed. Late into last night I was programming when I had an urge to eat. So I went to the kitchen, opened the frigde, pulled out a block of swiss, a tortilla and a hard-boiled egg... I cut the swiss into tiny blocks, placed it in the middle of the tortilla, peeled the shell off of the egg, and crumpled it's contents on top of the cheese... Opened the microwave, shoved it in, set it for a minute, and turned the TV on to HLN... I usually watch that and then a few hours of C-SPAN before going to bed...&lt;br /&gt;&lt;br /&gt;The microwave beeped and I went to get my food, as I heard over the speakers: "... new service allows people with certain medical attentions to find each other, free, and anonymous..." I rushed over to the TV, hit the rewind button on the Tivo, and sure has hell we'd made the news!&lt;br /&gt;&lt;br /&gt;So I ran into my roommate's room, and yelled at her to get up. We watched the segment, took a look at our membership numbers, and found that we'd gotten about 40 members since we had checked earlier in the morning! We're experiencing a heavy load at the moment... At JUST the wrong time, too. You heard me ramble on about the new Zippo for mod_python... Well, that's not ready yet. I was hoping to get a new site rolled out by Wed that would handle that kind of load, but now I'm really rushing it...&lt;br /&gt;&lt;br /&gt;Anyway, good news.... Just not great timing. mpZippo will be running a version of the site by Wednsday, hopefully. It seems to be a lot faster with certain tasks (like displaying raw data), and a little slower with others (continuations, etc)... But it's a hell of a lot more stable all the way around, and we won't be giving users any nasty little service drops...&lt;br /&gt;&lt;br /&gt;Take it easy everyone,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-114398755013168701?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/114398755013168701/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=114398755013168701' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114398755013168701'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114398755013168701'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/04/matchstdcom-hits-cnn.html' title='Matchstd.com Hits CNN!'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-114388299767079721</id><published>2006-04-01T02:13:00.000-07:00</published><updated>2006-11-15T21:19:50.964-07:00</updated><title type='text'>April Fool's on /.</title><content type='html'>Hahahahaha!&lt;br /&gt;&lt;br /&gt;I still can't stop laughing. This has got to be the funniest thing I've seen in a while now... It's probably because I'm real tired, but before it disappears into the dark abyss of internet history, here's slashdot today:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/screenshot.2.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/screenshot.2.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Happy April fool's day everyone!&lt;br /&gt;&lt;br /&gt;James&lt;br /&gt;&lt;br /&gt;Oh heck, almost forgot... My room-mate/business partner just completed a few intervies today for the matchstd.com site, and we made the news! We were on channel 7 and channel 4 news here in Albuququerque. As soon as I get some video I'll be sure to post it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-114388299767079721?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://slashdot.org' title='April Fool&apos;s on /.'/><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/114388299767079721/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=114388299767079721' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114388299767079721'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114388299767079721'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/04/april-fools-on.html' title='April Fool&apos;s on /.'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-114373062250124620</id><published>2006-03-30T07:56:00.000-07:00</published><updated>2006-11-15T21:19:50.845-07:00</updated><title type='text'>Zippo - A new handler for mod_python</title><content type='html'>Hello everyone,&lt;br /&gt;&lt;br /&gt;I've just started (and, surprisingly, am almost done) with a new project of mine. You've all probably worked with turbogears and cherrypy, and you're aware of how wonderful they can make life for python web developers. I've been using cherrypy for a while now with a framework of my own very similar to turbogears. In fact, the &lt;a href="http://www.matchstd.com"&gt;std matching site&lt;/a&gt; that I developed runs on it. I called it zippo. &lt;br /&gt;&lt;br /&gt;It got very complicated, as would be expected, and I decided recently I'd take a look into the code and start cleaning it up a bit further. That got me thinking of other development techniques, such as mod_python. I prefer mod_python over cherrypy, as it hooks directly into apache instead of needing to be run through its own server. It makes life a little easier to find hosting (although the folks at python-hosting.com do a good job). So I started to wonder if I could port the zippo cp stuff to mod_python. Sure enough, I found the way to do it, and created my own nifty handler. It's not nearly as full-featured as cherrypy, but it does the job well...&lt;br /&gt;&lt;br /&gt;So far I've got the following functional:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;path model (class hierarchy)&lt;/li&gt;&lt;li&gt;continuation-based modelling&lt;/li&gt;&lt;li&gt;RDBM-based sessions&lt;/li&gt;&lt;li&gt;templating (via cheetah, but easily changed)&lt;/li&gt;&lt;li&gt;configuration via the path model&lt;/li&gt;&lt;li&gt;user authentication&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I've still got a lot of work to do on refining it until it's ready for production, but I think I'm going to GPL it so all you people who never read my blog can use it, too. For a simple "Hello World" page I'm getting about 560 requests per second with ab (1.7 GHz Pentium4), and with a more complicated page involving user authentication and uncompiled cheetah templates, about 230 rps.. Not all that bad. Give me a few more days and I'll put out the first release.&lt;br /&gt;&lt;br /&gt;-James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-114373062250124620?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/114373062250124620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=114373062250124620' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114373062250124620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114373062250124620'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/03/zippo-new-handler-for-modpython_30.html' title='Zippo - A new handler for mod_python'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-114315145381514299</id><published>2006-03-23T14:59:00.000-07:00</published><updated>2006-11-15T21:19:50.620-07:00</updated><title type='text'>A new monitor!</title><content type='html'>Hello everyone.&lt;br /&gt;&lt;br /&gt;I'm happy. I finally decided to make an investment I should have made quite a while ago... A new monitor. I've been using the monitor on my laptop for a long time now. It's a 15 inch, but I use an additional keyboard, and my desk is small, so it was hard to get everything comfortable. When you spend 90% of your waking day in front of a computer, you better get everything nice and comfy. &lt;br /&gt;&lt;br /&gt;My roommate had switched out my desk chair a while back with a very nice office chair, which kept my rear soft and smooth, but my eyes were taking a beating... I'd like to show you now what this means with a screenshot at 1280x1024:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/6529/1119/1600/screenshot.1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/screenshot.1.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ha! Three strategically placed aterms and gvim open, in a way I can actually work with them! And look at how many lines of code I can get now! HAHAHA! I don't know if I'll ever be able to go back!&lt;br /&gt;&lt;br /&gt;Anyway, take it easy,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-114315145381514299?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/114315145381514299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=114315145381514299' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114315145381514299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114315145381514299'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/03/new-monitor.html' title='A new monitor!'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-114270752962727512</id><published>2006-03-18T11:41:00.000-07:00</published><updated>2006-11-15T21:19:50.542-07:00</updated><title type='text'>Google Wins Hearts and Minds of Geeky User Base! (And case in court)</title><content type='html'>If you haven't already heard from slashdot or the google blog (linked above), Google has won (to an extent) it's case in court. The government will not be getting all of the information it requested. In fact, it will be getting MUCH less. So go ahead and read the blog, and be happy that the best search engine today is still fighting for us. &lt;br /&gt;&lt;br /&gt;By the way, in case anybody wants to start a war here, I &lt;i&gt;do&lt;/i&gt; understand that fighting the government on this issue was in the best interest of the google share-holders, but I also realize that the interests of google's share-holders is in line with the interests of the general public in this case. I've read the debates on slashdot, so if you're looking for a fight, I'm ready to fight :)&lt;br /&gt;&lt;br /&gt;Take it easy everyone,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-114270752962727512?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://googleblog.blogspot.com/2006/03/judge-tells-doj-no-on-search-queries.html' title='Google Wins Hearts and Minds of Geeky User Base! (And case in court)'/><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/114270752962727512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=114270752962727512' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114270752962727512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114270752962727512'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/03/google-wins-hearts-and-minds-of-geeky.html' title='Google Wins Hearts and Minds of Geeky User Base! (And case in court)'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-114218935853300108</id><published>2006-03-12T11:43:00.000-07:00</published><updated>2006-11-15T21:19:50.445-07:00</updated><title type='text'>Hahahaha....</title><content type='html'>I have to post this... It's one of those little stupidities that don't really cause any harm, but really kind of mess up your day....&lt;br /&gt;&lt;br /&gt;I have a box running an svn server. I'm about to open that box up to the internet so that I can check out a copy and update my copy of a web application I'm working on via ssh on my host's server. I know the IP address, and I only want to allow connections from that server (I request a password, as well, but I'm kind of paranoid, and feel that the more levels of protection the better). So I ssh into the box from another box on my local network... I figure I'll quickly update iptables to block all requests that aren't from either my local network or the host's server. Since I have a default of accept on (It's behind firewall already, no traffic other than LAN hits it) iptables input... &lt;br /&gt;&lt;br /&gt;$ iptables -P INPUT DROP&lt;br /&gt;&lt;br /&gt;Ha! The bash prompt comes up... And every key I press doesn't get sent via ssh... &lt;br /&gt;&lt;br /&gt;That's probably one of the funniest things I've done yet (my rm -rf /usr/ slip was just sad). So, I have to restart my box, and hit my pride. I've not had to reboot that box EVER (other than for first installing slackware on it), but since I don't have a monitor or keyboard for it at the moment, I'm going to have to... ARGH!&lt;br /&gt;&lt;br /&gt;Take it easy,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-114218935853300108?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/114218935853300108/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=114218935853300108' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114218935853300108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114218935853300108'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/03/hahahaha.html' title='Hahahaha....'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-114051028232384358</id><published>2006-02-21T01:21:00.000-07:00</published><updated>2006-11-15T21:19:50.180-07:00</updated><title type='text'>First Project UP!</title><content type='html'>Hey everyone! I'm finally finished with the creation of my first real project, &lt;a href="http://www.matchstd.com"&gt;matchstd.com&lt;/a&gt;, a matching service designed for those with any type of sexually transmitted disease, which is completely free, and as anonymous as those things can get...&lt;br /&gt;&lt;br /&gt;There were a lot of challenges, but I think everything is pretty well worked out. It's done entirely in python, and hosted by the wonderful people over at http://www.python-hosting.com... I had a few problems getting a few features to work in their environment, but nothing too difficult. It's up and running now, and, I should add, in BETA, as I will be making bug fixes as they come up...&lt;br /&gt;&lt;br /&gt;Take it easy everyone, and take a look!&lt;br /&gt;&lt;br /&gt;-James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-114051028232384358?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.matchstd.com' title='First Project UP!'/><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/114051028232384358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=114051028232384358' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114051028232384358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114051028232384358'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/02/first-project-up.html' title='First Project UP!'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-113906925562276500</id><published>2006-02-04T08:57:00.000-07:00</published><updated>2006-11-15T21:19:50.053-07:00</updated><title type='text'>More sqlobject fun!</title><content type='html'>I got a hold of a load of locational information from a few government sources, and, being government sources, the information is scattered everywhere. I currently have a database with location information for the US, including zip codes and, most importantly, latitude and longitude. There are tons of areas in the world that the programs I was writing wouldn't reach, which is unfortunate for business. So I decided I'd find international information I could use. With the amount of trouble I had obtaining a US zip code database, I knew I wasn't going to be able to find information quite as specific, so I set my goal on latitude and longitude for cities around the world. I came across &lt;a href="http://earth-info.nga.mil/gns/html/"&gt;a ton of geographical data&lt;/a&gt; at that link, and downloaded their file. &lt;br /&gt;&lt;br /&gt;I updated my database schema to accept new values, this time based more on the city, province, country values than the zips themselves. My python script was supposed to parse all this data (big file), adding it to the new schema, and then pull the data from my old schema and append it, as well. I ran the program, went to watch some TV, and found a hefty little memory leak. My computer was losing ram, and losing it quickly. After about four hours staring at my code I figured it wasn't my fault, and took a look more deeply at what sqlobject was doing. It turns out that it holds a cache of the connection used to create each instance (I'm insantiating my sqlobject model to enter a record). This is a HUGE problem when you're entering as much data as I am, so I disabled it. Simply override the default _SO_finishCreate() method of the SQLObject class in your own model:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;class YourModel(SQLObject):&lt;br /&gt;    blah = StringCol()&lt;br /&gt;    etc = FloatCol()&lt;br /&gt;&lt;br /&gt;    ....&lt;br /&gt;&lt;br /&gt;    def _SO_finishCreate(self, id=None):&lt;br /&gt;        setters = self._SO_createValues.items()&lt;br /&gt;        names = [self.sqlmeta.columns[v[0]].dbName for v in setters]&lt;br /&gt;        values = [v[1] for v in setters]&lt;br /&gt;        self.dirty=False&lt;br /&gt;        if not self.sqlmeta.lazyUpdate:&lt;br /&gt;            del self._SO_createValues&lt;br /&gt;        else:&lt;br /&gt;            self._SO_createValues = {}&lt;br /&gt;        del self.sqlmeta._creating&lt;br /&gt;        id = self._connection.queryInsertID(self,&lt;br /&gt;                id, names, values)&lt;br /&gt;        self._init(id)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now you'll notice your ram not exceeding what you start off with during those inserts. Hope I've described this well enough for another person to find when they need it. Wish I could have found it earlier :)&lt;br /&gt;&lt;br /&gt;-James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-113906925562276500?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/113906925562276500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=113906925562276500' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113906925562276500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113906925562276500'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/02/more-sqlobject-fun.html' title='More sqlobject fun!'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-114086023499311194</id><published>2006-02-01T02:09:00.000-07:00</published><updated>2006-11-15T21:19:50.328-07:00</updated><title type='text'>Learning every day</title><content type='html'>Hello everybody. Like I was saying the other day, I got my first big site on the internet: &lt;a href="http://www.matchstd.com"&gt;matchstd.com&lt;/a&gt;, a location where individuals who have tested positive for any number of different stds (or just one), can find other individuals with the same stds... It's a good site, and it looks great (I'm no designer, but I'll give myself a pat on the back). &lt;br /&gt;&lt;br /&gt;I learned quite a few things putting this system up. My development computer has apache 2, &lt;a href="http://www.cherrypy.org"&gt;cherrypy 2.2beta&lt;/a&gt; and a plethora of other installed packages that make my life easier. The transition, however, to the main server (&lt;a href="http://www.python-hosting.com"&gt;python-hosting.com&lt;/a&gt;), made my life a little more difficult. Their service is great, but I had never moved a site that utilized so many features (I've stuck up PHP sites on various services, as well as some simple CGI and static pages), and was so complex. I'm just happy a solution out there existed for python hosting that already included most of what I needed (python 2.4, sqlobject, kid, etc.) Anyway, a few pointers:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Never program for a specific OS (I knew this before, but it's a good tip anyway). Always make sure that your application uses all the cross-platform tools available, instead of depending on hard-coded paths and such&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Organize your pages in a neat fashion. &lt;br /&gt;By placing pages in a huge mess throughout a large folder, you're going to eventually lose track of exactly where they are (or you'll depend on instinct for the path names)... Doing that will force you to re-organize on the server... Not good. I'll lay out a good organization model below...&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Keep track of your changes. Use a repository such as subversion or CVS. If you haven't used a repository before, go with subversion off the bat.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Make sure you've either programmed a nice way to keep log information organized, or use a program from the internet. I'd recommend &lt;a href="http://www.mrunix.net/webalizer/"&gt;webalizer&lt;/a&gt;, a completely free system that you cron, which produces lovely graphs and statistical printouts. It's extremely useful.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I'll put more up later... Or maybe not, but I hope some of those work out for you. Now, to the organization I mentioned. I've found the following setup makes things very easy to create both a web site, and programs that utilize the site's hidden engine:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;AppRoot&lt;/b&gt;&lt;/li&gt;&lt;br /&gt;    &lt;ul&gt;&lt;br /&gt;        &lt;li&gt;&lt;b&gt;html&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;            Use a templating system, and put all templates here. Your pages directory will include the code to display these.&lt;/li&gt; &lt;br /&gt;        &lt;li&gt;&lt;b&gt;libraries&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;            For every function that your web application needs to perform, it's a good idea to implement it here, in such a way that doesn't require the server. This lets you write simple non-web applications that can interact with your site. Although you won't need this at first, it's always good for later.&lt;/li&gt; &lt;br /&gt;        &lt;li&gt;&lt;b&gt;models&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;            Database definitions. Place all code to create your tables here.&lt;/li&gt;&lt;br /&gt;        &lt;li&gt;&lt;b&gt;pages&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;            Place all actual page logic display here... Basically, the code&lt;br /&gt;            that constructs each page.&lt;/li&gt;&lt;br /&gt;        &lt;li&gt;&lt;b&gt;server.py&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;            When I'm using CP, I like to put my server startup code here...&lt;br /&gt;        &lt;li&gt;&lt;b&gt;server.conf&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;            Also with CP, it's nice to have the configuration here.&lt;/li&gt;&lt;br /&gt;     &lt;/ul&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Okay. If anybody wants some input, feel free to comment!&lt;br /&gt;&lt;br /&gt;-James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-114086023499311194?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/114086023499311194/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=114086023499311194' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114086023499311194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/114086023499311194'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/02/learning-every-day.html' title='Learning every day'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-113744194199687649</id><published>2006-01-16T13:05:00.000-07:00</published><updated>2006-11-15T21:19:49.136-07:00</updated><title type='text'>CherryPy, SQLite, and SQLObject... A freaking mess!</title><content type='html'>Okay, well, maybe not so much. Turbogears uses all of these, so why wasn't my project properly accessing the database, instead giving me a whole load of threading errors? &lt;br /&gt;&lt;br /&gt;I was working with threading turned off without realizing it, and the second I turned the threadpool setting in Cherrypy to a non-zero value, I began getting loads of errors from SQLObject, stating that the thread that my database object was in was not the same as the one CP was using... So, where do you start? First of all, you take a look at:&lt;br /&gt;&lt;br /&gt;http://www.cherrypy.org/wiki/SQLObjectThreadPerConnection&lt;br /&gt;&lt;br /&gt;The solution posed works perfectly, assuming, of course, that you want to program your code specifically to use an sqlite database. The ideal solution is that instead of using the SQLiteConnection() method, we would just use our typical connectionForURI, with a simple URI. So, why does SQLObject throw up these errors, even when we're calling for a new connection with connectionForURI every time? I spent some time looking through SQLObject code, and found a little section in connectionForURI that looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    def connectionForURI(self, uri, **args):&lt;br /&gt;        if args:&lt;br /&gt;            if '?' not in uri:&lt;br /&gt;                uri += '?'&lt;br /&gt;            uri += urllib.urlencode(args)&lt;br /&gt;        if self.cachedURIs.has_key(uri):&lt;br /&gt;            return self.cachedURIs[uri]&lt;br /&gt;        if uri.find(':') != -1:&lt;br /&gt;            scheme, rest = uri.split(':', 1)&lt;br /&gt;            assert self.schemeBuilders.has_key(scheme), (&lt;br /&gt;                   "No SQLObject driver exists for %s (only %s)"&lt;br /&gt;                   % (scheme, ', '.join(self.schemeBuilders.keys())))&lt;br /&gt;            conn = self.schemeBuilders[scheme]().connectionFromURI(uri)&lt;br /&gt;        else:&lt;br /&gt;            # We just have a name, not a URI&lt;br /&gt;            assert self.instanceNames.has_key(uri),                    "No SQLObject driver exists under the name %s" % uri&lt;br /&gt;            conn = self.instanceNames[uri]&lt;br /&gt;        # @@: Do we care if we clobber another connection?&lt;br /&gt;        self.cachedURIs[uri] = conn&lt;br /&gt;        return conn&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It's located in the dbconnection.py file of the sqlobject source. Take a quick look, and you'll see that the first conditional checks for a cache of the connection. If it finds it, it will return the cached connection, instead of creating a new one. This works wonderfully for thread-safe databases such as mysql and postgres, but leads to problems with sqlite...&lt;br /&gt;&lt;br /&gt;The cachedURI's variable becomes accessable via the dbconnection.TheURIOpener object, which is simply an instantiation of the connectionForURI's parent class... So, there is a very simple solution:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if yourDBsURIString.startswith('sqlite'):&lt;br /&gt;    dbconnection.TheURIOpener.cachedURIs = {}&lt;br /&gt;connection = connectionForURI(yourDBsURIString)&lt;br /&gt;sqlhub.threadConnection = connection&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Place that in the list that CP starts whenever it makes a thread, and you won't have any more problems with sqlite threading and sqlobject. &lt;br /&gt;&lt;br /&gt;Until next time,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-113744194199687649?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/113744194199687649/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=113744194199687649' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113744194199687649'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113744194199687649'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/01/cherrypy-sqlite-and-sqlobject-freaking.html' title='CherryPy, SQLite, and SQLObject... A freaking mess!'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-113735050397995401</id><published>2006-01-15T11:06:00.000-07:00</published><updated>2006-11-15T21:19:49.044-07:00</updated><title type='text'>CherryPy Authentication Filter</title><content type='html'>I'm in the process of debugging a CP authentication filter that makes user authentication a whole lot easier. Once it's done, I'll try to find a way to put it up... HOSTING! GIVE ME! Anyway, use is very simple:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import userauth&lt;br /&gt;from userauth import authorize, UserAuth&lt;br /&gt;import cherrypy&lt;br /&gt;import os&lt;br /&gt;&lt;br /&gt;class Root():&lt;br /&gt;        @cherrypy.expose&lt;br /&gt;        def index(self):&lt;br /&gt;                return "This is always accessible by anyone."&lt;br /&gt;&lt;br /&gt;class Members(UserAuth):&lt;br /&gt;        """ Unless otherwise stated (secret()), no pages under this&lt;br /&gt;            module will be viewable by any member outside of the&lt;br /&gt;            members and admins groups. &lt;br /&gt;        """&lt;br /&gt;&lt;br /&gt; _db = 'sqlite:' + os.path.abspath('filename.db')&lt;br /&gt; _authorized = ['members', 'admins']&lt;br /&gt; _unauthorized = '/login' &lt;br /&gt;&lt;br /&gt; @cherrypy.expose&lt;br /&gt; def index(self):&lt;br /&gt;  return "You're only here if you are a member!"&lt;br /&gt;&lt;br /&gt; @authorize(['secret'], '/nowhere')&lt;br /&gt; @cherrypy.expose&lt;br /&gt; def secret(self):&lt;br /&gt;  # It would work to just make this another section all-together, but&lt;br /&gt;  # it could be useful...&lt;br /&gt;  return "Only members of secret can access this..."&lt;br /&gt;&lt;br /&gt;cherrypy.root = Root()&lt;br /&gt;cherrypy.root.members = Members()&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, you may be wondering, isn't that very similar to multiauth? Yes. There are differences though... For one, and the biggest, is the fact that you use a database connection through sqlobject. That's a big thing for turbogears, but I'm not sure what they've got out there already. My experience with turbogears is my experience with cherrypy and sqlobject, nothing more...&lt;br /&gt;&lt;br /&gt;Okay. I'm tired. I'll add to this later...&lt;br /&gt;&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-113735050397995401?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/113735050397995401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=113735050397995401' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113735050397995401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113735050397995401'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/01/cherrypy-authentication-filter.html' title='CherryPy Authentication Filter'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-113714182623694680</id><published>2006-01-13T01:34:00.000-07:00</published><updated>2006-11-15T21:19:48.935-07:00</updated><title type='text'>CherryPy Infinite Autoreload after Kid integration...</title><content type='html'>HA! This sucked... CherryPy v.2.1.0 and Kid 0.8. I've spent the last four hours trying to figure out why I couldn't get Kid to work properly with CherryPy... Even the simplest little examples from the website wouldn't function. Whenever I would start the Cherrypy server, it would continue to run, automatically starting itself again and again... The simple solution was to turn off autoreload by setting the server up as production:&lt;br /&gt;&lt;br /&gt;cherrypy.config.update({'server.environment':'production'})&lt;br /&gt;&lt;br /&gt;But not having the automatic reload on during development is a pain. I don't want to have to continue to restart my server whenever I make the tiniest change in the code... I like to see the instant results... The way I remember with PHP... Alt-F1 (Move to browser workspace), CTRL-R (reload page). So I needed to find a fix, and I started working through all of tracks to see if anything related. I came across a change to the autoreload abilities of cherrypy made by turbogears... It told me where autoreload was, and what it was called, so I went and hacked some source...&lt;br /&gt;&lt;br /&gt;I ended up changing the cherrypy/lib/autoreload.py file in cherrypy. Replace the reloader_thread() function with this (don't say a thing about indentation. Blogger messes that up even with pre tags... So, if you found this helpful, get me some god damned hosting!):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def reloader_thread():&lt;br /&gt;    mtimes = {}&lt;br /&gt;    &lt;br /&gt;    def fileattr(m):&lt;br /&gt;        return getattr(m, "__file__", None)&lt;br /&gt;  &lt;br /&gt;    while RUN_RELOADER:&lt;br /&gt;        modlist = sys.modules.values()&lt;br /&gt;        for filename in filter(lambda v: v, map(lambda m: getattr(m, "__file__", None), modlist)):&lt;br /&gt;            if filename and os.path.exists(filename):&lt;br /&gt;                if filename.endswith(".kid") or filename == "&lt;string&gt;":&lt;br /&gt;                    continue&lt;br /&gt;                if filename.endswith(".pyc"):&lt;br /&gt;                    filename = filename[:-1]&lt;br /&gt;                try:&lt;br /&gt;                    mtime = os.stat(filename).st_mtime&lt;br /&gt;                except OSError, e:&lt;br /&gt;                    sys.exit(3) # force reload&lt;br /&gt;                if filename not in mtimes:&lt;br /&gt;                    mtimes[filename] = mtime&lt;br /&gt;                    continue&lt;br /&gt;                if mtime &gt; mtimes[filename]:&lt;br /&gt;                    sys.exit(3) # force reload&lt;br /&gt;        time.sleep(1)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And restart your server... Hopefully, you'll have the same luck I did, and be able to use your server in development mode again! &lt;br /&gt;&lt;br /&gt;The problem was simply that cherrypy didn't like eggs that were stored in zip format, and OSError would be raised whenever it encountered one. The biggest change is the os.path.exists() call, which makes sure that cherrypy thinks that an egg is a directory, and it isn't, it won't call it... It seems to work for now, but again, I don't know what the side affects are, so use at your own risk...&lt;br /&gt;&lt;br /&gt;Good day,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-113714182623694680?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/113714182623694680/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=113714182623694680' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113714182623694680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113714182623694680'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/01/cherrypy-infinite-autoreload-after-kid.html' title='CherryPy Infinite Autoreload after Kid integration...'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-113707813792248715</id><published>2006-01-12T07:46:00.000-07:00</published><updated>2006-11-15T21:19:48.843-07:00</updated><title type='text'>SQLObject and multiple database connections (SQLite)</title><content type='html'>After writing a functional, yet somewhat limited database connection module for all my python database needs, I came across SQLObject. It sucks to find something that does what you want better than what you've got after you've put so much time into your own solution. So, SQLObject being open source, fast, clever and incredibly easy to use, I decided I'd give it a try. I also decided I'd use sqlite for my project, making things a little more modular and simple to use. So my rewrite of my ratings system began...&lt;br /&gt;&lt;br /&gt;It took only about an hour and half to finish the new module, and it worked wonderfully in my simple tests. sqlite was probably one of the better systems I've worked with. Postgres is just too large and painful to get working properly for small projects... On top of that, sqlobject provided the access necessary to immediately port my application to postgres if I needed it. So, I fire up vim and start writing a product module, which is a general-purpose module for working with an index of products. I decided on using a separate sqlite database for that one, so I could place all my separate databases in a single directory, and back them up as necessary, etc. It was the perfect idea, until it went totally wrong :)&lt;br /&gt;&lt;br /&gt;SQLite provides the sqlhub, which, as it states, is a hub for processing connections... Skimming the documentation, I didn't see much about it... And for good reason. Most of the time you won't be using multiple sqlite databases in the same program... So I set up each of my modules to use sqlhub.(thread|process)Connection to define the connection that they would use, thinking that the namespace would prevent any problems. Not so... Every time I'd try using both modules together I'd end up with a glaring python traceback pointing to some pysqlite internals... &lt;br /&gt;&lt;br /&gt;So I've spent the past few hours googling around, and I've finally found a way to get this to work... I'd actually passed by the solution earlier in my hunting through __doc__'s in sqlobject, but didn't read it right... Anyway, take a look at:&lt;br /&gt;&lt;br /&gt;help(sqlobject.dbconnection.ConnectionHub)&lt;br /&gt;&lt;br /&gt;That's where the answer lies. It's too freaking simple :)&lt;br /&gt;&lt;br /&gt;Just set up your modules to each use their own specific connections:&lt;br /&gt;&lt;br /&gt;Module 1:&lt;br /&gt;&lt;br /&gt;dbConnectionA = dbconnection.ConnectionHub()&lt;br /&gt;&lt;br /&gt;class tableForA(SQLObject):&lt;br /&gt;   """ A table for module 1 """&lt;br /&gt;   &lt;br /&gt;   _connection = dbConnectionA&lt;br /&gt;          ...&lt;br /&gt;dbConnectionA.threadConnection = connectionForURI(dbfile)&lt;br /&gt;&lt;br /&gt;Module 2:&lt;br /&gt;&lt;br /&gt;dbConnectionB = dbconnection.ConnectionHub()&lt;br /&gt;&lt;br /&gt;class tableForB(SQLObject):&lt;br /&gt;   """ A table for module 2 """&lt;br /&gt;&lt;br /&gt;   _connection = dbConnectionB&lt;br /&gt;          ...&lt;br /&gt;&lt;br /&gt;And now you can use the modules together without any conflicting connections. I've yet to apply these to cherrpy, which I hear can be problematic due to SQLite's lack of happy threading support... That's for tomorrow... &lt;br /&gt;&lt;br /&gt;-James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-113707813792248715?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/113707813792248715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=113707813792248715' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113707813792248715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113707813792248715'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/01/sqlobject-and-multiple-database.html' title='SQLObject and multiple database connections (SQLite)'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-113636606985045979</id><published>2006-01-04T01:54:00.000-07:00</published><updated>2006-11-15T21:19:48.727-07:00</updated><title type='text'>My vmware experience with slackware</title><content type='html'>Hello everyone, I've been playing around with VMware recently... A program that allows you to create virtual machines (thus VM), which are simply virtual computers on which you can run a variety of operating systems and such. The benefits such software makes to the programming world are unimaginable. VMs are used to study viruses and develop operating systems, as when something goes wrong, they can simply be deleted, and are always isolated from the system.&lt;br /&gt;&lt;br /&gt;So I started by getting a copy of VMWorkstation, and attempting an install on my system. Of course, slackware isn't supported, and I ended up having to create a few directories in etc:&lt;br /&gt;&lt;br /&gt;rc0.d, rc1.d, rc2.d, rc3.d, rc4.d, rc5.d, rc6.d, and rc.initd&lt;br /&gt;&lt;br /&gt;After that, I was able to get the installation script to run, and could get the configuration script to run as well. The problem was that none of the created modules would install, and I'd always get a message along the lines of "VMware is installed, but not properly configured. Please (re-)configure VMware by running the vmware-config.pl script."&lt;br /&gt;&lt;br /&gt;I struggled with it for a while, and then decided I had to be making a mistake. Others had reported successful installations of VMware on slackware... And then I figured it out. I haden't enabled module unloading in my kernel! So, as today was the release of linux kernel 2.6.15, I decided I'd update and enable the unloading. The new kernel was named elmers (glue bottle on my desk), and after proper configuration I rebooted. &lt;br /&gt;&lt;br /&gt;Elmers worked just fine, and everything started up normally. Good stuff... So I made my first virtual machine, Windows XP. I develop a lot of stuff for the web, and Internet Explorer is unfortunately pretty hot with the masses, so I had to keep a machine dedicated to windows just so I could use IE... Switching between machines was tedious. I could have done a dual boot, but that takes forever, and since I often serve the pages straight from my development machine, I wouldn't have too good a time with that method. VMware was a godsend!&lt;br /&gt;&lt;br /&gt;I set VMware to use the XP install CD, and started up the machine. The VMware boot screen came up, and then the windows install.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/screenshot.0.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/screenshot.0.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; A good two hours later I had a functional Windows XP machine!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/screenshot2.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/screenshot2.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; This got me to thinking... All those people I wanted to convert to linux... I now had the tool to do it! They would never have to leave behind that software they love for some reason. So I installed America Online on the virtual machine, made sure it worked, and approached my room mate... &lt;br /&gt;&lt;br /&gt;Me: "I can put linux on your computer now."&lt;br /&gt;Her: "Can I use AOL?"&lt;br /&gt;Me: "Yes"&lt;br /&gt;Her: "Can I play my games?"&lt;br /&gt;Me: "Yes"&lt;br /&gt;Her: "What about my roms?"&lt;br /&gt;Me: "Yep"&lt;br /&gt;Her: "And my music?"&lt;br /&gt;Me: "You can do that in linux. You need to use it for everything that you can."&lt;br /&gt;Her: "We'll talk later"&lt;br /&gt;&lt;br /&gt;I've never gotten that far before. Now when I notice attacks on the wireless networks, I can just replace her VM, and I don't have to worry any more. &lt;br /&gt;&lt;br /&gt;Oh yeah, and bow down mortals:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/macosx.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/macosx.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/macosx-waitingforsafari.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/macosx-waitingforsafari.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;That's right. You know what it is. Way to damn slow to work with, but it's a start... Waiting for full intel support :)&lt;br /&gt;&lt;br /&gt;-James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-113636606985045979?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/113636606985045979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=113636606985045979' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113636606985045979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113636606985045979'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2006/01/my-vmware-experience-with-slackware.html' title='My vmware experience with slackware'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-113597615521736898</id><published>2005-12-30T13:40:00.000-07:00</published><updated>2006-11-15T21:19:48.645-07:00</updated><title type='text'>Christmas has come and gone</title><content type='html'>Sorry I haven't been posting recently. It was Christmas, after all. A time when persons of all religions may gather in harmony ;). &lt;br /&gt;&lt;br /&gt;I got what I wanted. A nice 60GB 5th gen. iPod... Beautiful piece of technology. And, being the linux user I am, I thought it would take quite a bit for me to get this thing functioning, but was wrong. Here's what I had to do:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Plug it in.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Check dmesg for the location. It entered my /dev filesystem at sda. Yours may be sdb, or sdc, if you're using several USB storage devices.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Download &lt;a href="http://www.gtkpod.org/about.html"&gt;gtkPod&lt;/a&gt; sources.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;./configure &amp;&amp; make &amp;&amp; make install&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Mount /dev/sdX2 to /mnt/ipod&lt;br&gt;&lt;br /&gt;I ended up getting the windows formatted system. Not too sure if that's the standard these days. If not, you'll &lt;br /&gt;probably have to specify the mac filesystem (otherwise it's fat32) It's easier to set it up in fstab, and make sure you give your normal user permissions to access the drive.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Start gtkpod as a user with access to the drive.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Add all the music you've got.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Click sync, and let gtkpod write the itunesdb file. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Unmount the partition: umount /dev/sda2&lt;/li&gt;&lt;br /&gt;&lt;li&gt;From what I've seen, that should do it for you, and you can unplug it even if you see the "Do not Disconnect" message. If you're still scared (or just want to charge it and play music at the same time), just # eject /dev/sda&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You're set... You can use &lt;a href="http://ffmpeg.sourceforge.net/index.php"&gt;ffmpeg&lt;/a&gt; to convert video to the proper format. I've written a very small python script so I don't have to remember everything:&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;#! /usr/bin/env python&lt;br /&gt;&lt;br /&gt;import sys,os&lt;br /&gt;&lt;br /&gt;try:&lt;br /&gt; avifile = sys.argv[1]&lt;br /&gt; output = sys.argv[2]&lt;br /&gt;&lt;br /&gt;# os.system("""/usr/bin/ffmpeg -vcodec xvid -b 300 -qmin 3 -qmax 5 -bufsize 4096 -g&lt;br /&gt;#   300 -acodec aac -ab 96 -i %s -s 320x240 -aspect 4:3 %s""", (avifile,&lt;br /&gt;#    output))&lt;br /&gt;&lt;br /&gt; print "Input file: %s" % avifile&lt;br /&gt; print "Output file: %s" % output&lt;br /&gt; os.system("""/usr/bin/ffmpeg -b 300 -qmax 5 -g 300 -i %s -f mov %s""" % (avifile,output))&lt;br /&gt; print "Done."&lt;br /&gt;except:&lt;br /&gt; print "Error occurred!"&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Till next time,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-113597615521736898?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/113597615521736898/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=113597615521736898' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113597615521736898'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113597615521736898'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/12/christmas-has-come-and-gone.html' title='Christmas has come and gone'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-113508991690069813</id><published>2005-12-20T07:40:00.000-07:00</published><updated>2006-11-15T21:19:48.553-07:00</updated><title type='text'>Linux log monitor</title><content type='html'>Okay, so I've been thinking for a while how nice it would be to have a little message pop up on my screen whenever something was added to one of my logs, and I didn't really want to work on something I'd get rid of quickly, so I never worked on the program. Today though I learned about xmessage (Which shows I've still got a long way to go with this whole linux thing :)). I threw together a quick python script that monitors logs for you:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;#! /usr/bin/env python&lt;br /&gt;&lt;br /&gt;""" A very simple monitor, using xmessage to display information about an update to any file...  """&lt;br /&gt;&lt;br /&gt;import os, time &lt;br /&gt;&lt;br /&gt;# Will check each item, takes the form of 'command to read log, identifier, and last line read (leave empty)...&lt;br /&gt;&lt;br /&gt;reader = [&lt;br /&gt;  ['dmesg', 'System Logs', ''],&lt;br /&gt;  ['cat /var/log/apache/error_log', 'Apache Error', ''],&lt;br /&gt;  ['cat /var/log/apache/access_log', 'Apache', '']&lt;br /&gt; ]&lt;br /&gt;&lt;br /&gt;while 1:&lt;br /&gt; for command in reader:&lt;br /&gt;  read = os.popen("%s | tail -n 1" % command[0])&lt;br /&gt;  line = read.readlines()&lt;br /&gt;  if line[0] &lt;&gt; command[2]:&lt;br /&gt;   if command[2] &lt;&gt; "":&lt;br /&gt;    os.popen("echo \"%s: %s\" | xmessage -center -file - -timeout 3" % (command[1], line[0]))&lt;br /&gt;    time.sleep(0.3)&lt;br /&gt;   command[2] = line[0]&lt;br /&gt; time.sleep(1) &lt;br /&gt; &lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-113508991690069813?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/113508991690069813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=113508991690069813' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113508991690069813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113508991690069813'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/12/linux-log-monitor.html' title='Linux log monitor'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-113463619561039313</id><published>2005-12-15T01:35:00.000-07:00</published><updated>2006-11-15T21:19:48.469-07:00</updated><title type='text'>Getting more interested in Python</title><content type='html'>What's up everyone? I've been reading up a little more on Python... I knew enough to quickly debug runtime errors in python stuff that I downloaded, but never really got into programming with the language. When I decided that I didn't like bash scripting, and needed to get a job done, I turned to CLI PHP... Which is definitely not fun to program with.&lt;br /&gt;&lt;br /&gt;I love PHP for web scripting. It's extremely simple to get a quick site off of the ground, and comes available with almost every hosting plan you'd ever look into, but let's face it, PHP is NOT ready for more traditional, single-computer based languages. I read up a little on PHP GTK, which looked interesting, but a little too complicated for my taste. And, by the way, why do I want to rely on a language that's just recently gained good CLI capabilities... I want a full-featured language that I can use for anything. And that's what got me interested enough in python to put some effort into learning it. &lt;br /&gt;&lt;br /&gt;So I picked up the Python in a Nutshell book, and started reading. This really is a nice little language. I've written some very simple scripts thus far... This one, my most recent, shows my lack of understanding thus far, but works:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;#! /usr/bin/python&lt;br /&gt;&lt;br /&gt;# Simple script for raising, lowering, or directly setting the processor throttling state...&lt;br /&gt;# Takes a single argument, either n, an integer smaller than max_state and larger than min_state,&lt;br /&gt;# or +, which increments the state, or -, which decrements the state.&lt;br /&gt;&lt;br /&gt;import os,sys&lt;br /&gt;&lt;br /&gt;throttling_file = "/proc/acpi/processor/CPU1/throttling"&lt;br /&gt;max_state = 7&lt;br /&gt;min_state = 0&lt;br /&gt;&lt;br /&gt;def changestate(state="0"):&lt;br /&gt; global throttling_file,max_state,min_state&lt;br /&gt;&lt;br /&gt; def getcurrentstate():&lt;br /&gt;  "Get the processor's current throttle state... "&lt;br /&gt; &lt;br /&gt;  file = open(throttling_file, "r")&lt;br /&gt;  while 1:&lt;br /&gt;   str = file.readline()&lt;br /&gt;   if str == "": return None&lt;br /&gt;   if str.find("*") &gt; -1:&lt;br /&gt;    start = str.find("*") + 2&lt;br /&gt;    level = str[start:start+1]&lt;br /&gt;    return int(level)&lt;br /&gt;  return None&lt;br /&gt;  &lt;br /&gt; if state == "+":&lt;br /&gt;  state = str(getcurrentstate() + 1)&lt;br /&gt; elif state == "-":&lt;br /&gt;  state = str(getcurrentstate() -1)&lt;br /&gt; &lt;br /&gt; if int(state) &gt; max_state or int(state) &lt; min_state:&lt;br /&gt;  print "Cannot set specified state. State remains at %i" % getcurrentstate()&lt;br /&gt;  sys.exit()&lt;br /&gt; else:&lt;br /&gt;  print "Setting processor throttling to level %s" % state&lt;br /&gt;  os.system("echo -n %s &gt; %s" % (state,throttling_file))&lt;br /&gt;&lt;br /&gt;if len(sys.argv) &lt;&gt; 2:&lt;br /&gt; print "Setting processor throttling to default, state 0. Only call this script with one argument."&lt;br /&gt; state = "0"&lt;br /&gt;else:&lt;br /&gt; state = sys.argv[1]&lt;br /&gt;&lt;br /&gt;changestate(state)&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;All it does is set my processor's throttling... I can pass a throttling level, or a + / -, and it will adjust the processor level accordingly... I could add quite a bit more, but it does what I need. I've bound it to keyboard shortcuts, and can throttle my processor as I feel fit... Good stuff... I'll be back,&lt;br /&gt;&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-113463619561039313?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/113463619561039313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=113463619561039313' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113463619561039313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113463619561039313'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/12/getting-more-interested-in-python.html' title='Getting more interested in Python'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-113353177068353735</id><published>2005-12-02T06:55:00.000-07:00</published><updated>2006-11-15T21:19:48.372-07:00</updated><title type='text'>Balance CN6555 Notebook - Slackware</title><content type='html'>Hello everyone! I've got this new (relative) laptop pretty much running, and decided it's about time to lay out my configuration. These may not be perfect (I'm waiting, for instance, on some more specific processor settings)... But they'll get you started...&lt;br /&gt;&lt;br /&gt;Extras I've got:&lt;br /&gt;External Mouse (MS Optical)&lt;br /&gt;External Keyboard (MS Natural)&lt;br /&gt;USB Flash drive (Kingston 1GB)&lt;br /&gt;512 MB RAM&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;font-weight:bold"&gt;Kernel Configuration (2.6.14.3)&lt;/span&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;#&lt;br /&gt;# Automatically generated make config: don't edit&lt;br /&gt;# Linux kernel version: 2.6.14.3&lt;br /&gt;# Wed Nov 30 05:41:31 2005&lt;br /&gt;#&lt;br /&gt;CONFIG_X86=y&lt;br /&gt;CONFIG_SEMAPHORE_SLEEPERS=y&lt;br /&gt;CONFIG_MMU=y&lt;br /&gt;CONFIG_UID16=y&lt;br /&gt;CONFIG_GENERIC_ISA_DMA=y&lt;br /&gt;CONFIG_GENERIC_IOMAP=y&lt;br /&gt;CONFIG_ARCH_MAY_HAVE_PC_FDC=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Code maturity level options&lt;br /&gt;#&lt;br /&gt;CONFIG_EXPERIMENTAL=y&lt;br /&gt;CONFIG_CLEAN_COMPILE=y&lt;br /&gt;CONFIG_BROKEN_ON_SMP=y&lt;br /&gt;CONFIG_LOCK_KERNEL=y&lt;br /&gt;CONFIG_INIT_ENV_ARG_LIMIT=32&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# General setup&lt;br /&gt;#&lt;br /&gt;CONFIG_LOCALVERSION=""&lt;br /&gt;CONFIG_LOCALVERSION_AUTO=y&lt;br /&gt;CONFIG_SWAP=y&lt;br /&gt;CONFIG_SYSVIPC=y&lt;br /&gt;CONFIG_POSIX_MQUEUE=y&lt;br /&gt;# CONFIG_BSD_PROCESS_ACCT is not set&lt;br /&gt;CONFIG_SYSCTL=y&lt;br /&gt;CONFIG_AUDIT=y&lt;br /&gt;CONFIG_AUDITSYSCALL=y&lt;br /&gt;CONFIG_HOTPLUG=y&lt;br /&gt;CONFIG_KOBJECT_UEVENT=y&lt;br /&gt;CONFIG_IKCONFIG=y&lt;br /&gt;# CONFIG_IKCONFIG_PROC is not set&lt;br /&gt;CONFIG_INITRAMFS_SOURCE=""&lt;br /&gt;# CONFIG_EMBEDDED is not set&lt;br /&gt;CONFIG_KALLSYMS=y&lt;br /&gt;# CONFIG_KALLSYMS_EXTRA_PASS is not set&lt;br /&gt;CONFIG_PRINTK=y&lt;br /&gt;CONFIG_BUG=y&lt;br /&gt;CONFIG_BASE_FULL=y&lt;br /&gt;CONFIG_FUTEX=y&lt;br /&gt;CONFIG_EPOLL=y&lt;br /&gt;CONFIG_SHMEM=y&lt;br /&gt;CONFIG_CC_ALIGN_FUNCTIONS=0&lt;br /&gt;CONFIG_CC_ALIGN_LABELS=0&lt;br /&gt;CONFIG_CC_ALIGN_LOOPS=0&lt;br /&gt;CONFIG_CC_ALIGN_JUMPS=0&lt;br /&gt;# CONFIG_TINY_SHMEM is not set&lt;br /&gt;CONFIG_BASE_SMALL=0&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Loadable module support&lt;br /&gt;#&lt;br /&gt;CONFIG_MODULES=y&lt;br /&gt;# CONFIG_MODULE_UNLOAD is not set&lt;br /&gt;CONFIG_OBSOLETE_MODPARM=y&lt;br /&gt;# CONFIG_MODVERSIONS is not set&lt;br /&gt;# CONFIG_MODULE_SRCVERSION_ALL is not set&lt;br /&gt;CONFIG_KMOD=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Processor type and features&lt;br /&gt;#&lt;br /&gt;CONFIG_X86_PC=y&lt;br /&gt;# CONFIG_X86_ELAN is not set&lt;br /&gt;# CONFIG_X86_VOYAGER is not set&lt;br /&gt;# CONFIG_X86_NUMAQ is not set&lt;br /&gt;# CONFIG_X86_SUMMIT is not set&lt;br /&gt;# CONFIG_X86_BIGSMP is not set&lt;br /&gt;# CONFIG_X86_VISWS is not set&lt;br /&gt;# CONFIG_X86_GENERICARCH is not set&lt;br /&gt;# CONFIG_X86_ES7000 is not set&lt;br /&gt;# CONFIG_M386 is not set&lt;br /&gt;# CONFIG_M486 is not set&lt;br /&gt;# CONFIG_M586 is not set&lt;br /&gt;# CONFIG_M586TSC is not set&lt;br /&gt;# CONFIG_M586MMX is not set&lt;br /&gt;# CONFIG_M686 is not set&lt;br /&gt;# CONFIG_MPENTIUMII is not set&lt;br /&gt;# CONFIG_MPENTIUMIII is not set&lt;br /&gt;CONFIG_MPENTIUMM=y&lt;br /&gt;# CONFIG_MPENTIUM4 is not set&lt;br /&gt;# CONFIG_MK6 is not set&lt;br /&gt;# CONFIG_MK7 is not set&lt;br /&gt;# CONFIG_MK8 is not set&lt;br /&gt;# CONFIG_MCRUSOE is not set&lt;br /&gt;# CONFIG_MEFFICEON is not set&lt;br /&gt;# CONFIG_MWINCHIPC6 is not set&lt;br /&gt;# CONFIG_MWINCHIP2 is not set&lt;br /&gt;# CONFIG_MWINCHIP3D is not set&lt;br /&gt;# CONFIG_MGEODEGX1 is not set&lt;br /&gt;# CONFIG_MCYRIXIII is not set&lt;br /&gt;# CONFIG_MVIAC3_2 is not set&lt;br /&gt;# CONFIG_X86_GENERIC is not set&lt;br /&gt;CONFIG_X86_CMPXCHG=y&lt;br /&gt;CONFIG_X86_XADD=y&lt;br /&gt;CONFIG_X86_L1_CACHE_SHIFT=6&lt;br /&gt;CONFIG_RWSEM_XCHGADD_ALGORITHM=y&lt;br /&gt;CONFIG_GENERIC_CALIBRATE_DELAY=y&lt;br /&gt;CONFIG_X86_WP_WORKS_OK=y&lt;br /&gt;CONFIG_X86_INVLPG=y&lt;br /&gt;CONFIG_X86_BSWAP=y&lt;br /&gt;CONFIG_X86_POPAD_OK=y&lt;br /&gt;CONFIG_X86_GOOD_APIC=y&lt;br /&gt;CONFIG_X86_INTEL_USERCOPY=y&lt;br /&gt;CONFIG_X86_USE_PPRO_CHECKSUM=y&lt;br /&gt;CONFIG_HPET_TIMER=y&lt;br /&gt;# CONFIG_SMP is not set&lt;br /&gt;# CONFIG_PREEMPT_NONE is not set&lt;br /&gt;# CONFIG_PREEMPT_VOLUNTARY is not set&lt;br /&gt;CONFIG_PREEMPT=y&lt;br /&gt;CONFIG_PREEMPT_BKL=y&lt;br /&gt;CONFIG_X86_UP_APIC=y&lt;br /&gt;CONFIG_X86_UP_IOAPIC=y&lt;br /&gt;CONFIG_X86_LOCAL_APIC=y&lt;br /&gt;CONFIG_X86_IO_APIC=y&lt;br /&gt;CONFIG_X86_TSC=y&lt;br /&gt;CONFIG_X86_MCE=y&lt;br /&gt;# CONFIG_X86_MCE_NONFATAL is not set&lt;br /&gt;# CONFIG_X86_MCE_P4THERMAL is not set&lt;br /&gt;# CONFIG_TOSHIBA is not set&lt;br /&gt;# CONFIG_I8K is not set&lt;br /&gt;# CONFIG_X86_REBOOTFIXUPS is not set&lt;br /&gt;# CONFIG_MICROCODE is not set&lt;br /&gt;# CONFIG_X86_MSR is not set&lt;br /&gt;# CONFIG_X86_CPUID is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Firmware Drivers&lt;br /&gt;#&lt;br /&gt;# CONFIG_EDD is not set&lt;br /&gt;# CONFIG_DELL_RBU is not set&lt;br /&gt;# CONFIG_DCDBAS is not set&lt;br /&gt;CONFIG_NOHIGHMEM=y&lt;br /&gt;# CONFIG_HIGHMEM4G is not set&lt;br /&gt;# CONFIG_HIGHMEM64G is not set&lt;br /&gt;CONFIG_SELECT_MEMORY_MODEL=y&lt;br /&gt;CONFIG_FLATMEM_MANUAL=y&lt;br /&gt;# CONFIG_DISCONTIGMEM_MANUAL is not set&lt;br /&gt;# CONFIG_SPARSEMEM_MANUAL is not set&lt;br /&gt;CONFIG_FLATMEM=y&lt;br /&gt;CONFIG_FLAT_NODE_MEM_MAP=y&lt;br /&gt;# CONFIG_SPARSEMEM_STATIC is not set&lt;br /&gt;# CONFIG_MATH_EMULATION is not set&lt;br /&gt;# CONFIG_MTRR is not set&lt;br /&gt;# CONFIG_EFI is not set&lt;br /&gt;# CONFIG_REGPARM is not set&lt;br /&gt;CONFIG_SECCOMP=y&lt;br /&gt;# CONFIG_HZ_100 is not set&lt;br /&gt;# CONFIG_HZ_250 is not set&lt;br /&gt;CONFIG_HZ_1000=y&lt;br /&gt;CONFIG_HZ=1000&lt;br /&gt;CONFIG_PHYSICAL_START=0x100000&lt;br /&gt;# CONFIG_KEXEC is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Power management options (ACPI, APM)&lt;br /&gt;#&lt;br /&gt;CONFIG_PM=y&lt;br /&gt;# CONFIG_PM_DEBUG is not set&lt;br /&gt;CONFIG_SOFTWARE_SUSPEND=y&lt;br /&gt;CONFIG_PM_STD_PARTITION="/dev/hda5"&lt;br /&gt;# CONFIG_SWSUSP_ENCRYPT is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# ACPI (Advanced Configuration and Power Interface) Support&lt;br /&gt;#&lt;br /&gt;CONFIG_ACPI=y&lt;br /&gt;# CONFIG_ACPI_SLEEP is not set&lt;br /&gt;CONFIG_ACPI_AC=y&lt;br /&gt;CONFIG_ACPI_BATTERY=y&lt;br /&gt;CONFIG_ACPI_BUTTON=y&lt;br /&gt;# CONFIG_ACPI_VIDEO is not set&lt;br /&gt;# CONFIG_ACPI_HOTKEY is not set&lt;br /&gt;CONFIG_ACPI_FAN=y&lt;br /&gt;CONFIG_ACPI_PROCESSOR=y&lt;br /&gt;CONFIG_ACPI_THERMAL=y&lt;br /&gt;# CONFIG_ACPI_ASUS is not set&lt;br /&gt;# CONFIG_ACPI_IBM is not set&lt;br /&gt;# CONFIG_ACPI_TOSHIBA is not set&lt;br /&gt;CONFIG_ACPI_BLACKLIST_YEAR=0&lt;br /&gt;# CONFIG_ACPI_DEBUG is not set&lt;br /&gt;CONFIG_ACPI_EC=y&lt;br /&gt;CONFIG_ACPI_POWER=y&lt;br /&gt;CONFIG_ACPI_SYSTEM=y&lt;br /&gt;# CONFIG_X86_PM_TIMER is not set&lt;br /&gt;# CONFIG_ACPI_CONTAINER is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# APM (Advanced Power Management) BIOS Support&lt;br /&gt;#&lt;br /&gt;# CONFIG_APM is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# CPU Frequency scaling&lt;br /&gt;#&lt;br /&gt;CONFIG_CPU_FREQ=y&lt;br /&gt;CONFIG_CPU_FREQ_TABLE=m&lt;br /&gt;# CONFIG_CPU_FREQ_DEBUG is not set&lt;br /&gt;# CONFIG_CPU_FREQ_STAT is not set&lt;br /&gt;# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set&lt;br /&gt;CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y&lt;br /&gt;CONFIG_CPU_FREQ_GOV_PERFORMANCE=y&lt;br /&gt;# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set&lt;br /&gt;CONFIG_CPU_FREQ_GOV_USERSPACE=y&lt;br /&gt;# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set&lt;br /&gt;# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# CPUFreq processor drivers&lt;br /&gt;#&lt;br /&gt;# CONFIG_X86_ACPI_CPUFREQ is not set&lt;br /&gt;# CONFIG_X86_POWERNOW_K6 is not set&lt;br /&gt;# CONFIG_X86_POWERNOW_K7 is not set&lt;br /&gt;# CONFIG_X86_POWERNOW_K8 is not set&lt;br /&gt;# CONFIG_X86_GX_SUSPMOD is not set&lt;br /&gt;# CONFIG_X86_SPEEDSTEP_CENTRINO is not set&lt;br /&gt;# CONFIG_X86_SPEEDSTEP_ICH is not set&lt;br /&gt;# CONFIG_X86_SPEEDSTEP_SMI is not set&lt;br /&gt;# CONFIG_X86_P4_CLOCKMOD is not set&lt;br /&gt;# CONFIG_X86_CPUFREQ_NFORCE2 is not set&lt;br /&gt;# CONFIG_X86_LONGRUN is not set&lt;br /&gt;# CONFIG_X86_LONGHAUL is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# shared options&lt;br /&gt;#&lt;br /&gt;# CONFIG_X86_SPEEDSTEP_LIB is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Bus options (PCI, PCMCIA, EISA, MCA, ISA)&lt;br /&gt;#&lt;br /&gt;CONFIG_PCI=y&lt;br /&gt;# CONFIG_PCI_GOBIOS is not set&lt;br /&gt;# CONFIG_PCI_GOMMCONFIG is not set&lt;br /&gt;# CONFIG_PCI_GODIRECT is not set&lt;br /&gt;CONFIG_PCI_GOANY=y&lt;br /&gt;CONFIG_PCI_BIOS=y&lt;br /&gt;CONFIG_PCI_DIRECT=y&lt;br /&gt;CONFIG_PCI_MMCONFIG=y&lt;br /&gt;CONFIG_PCIEPORTBUS=y&lt;br /&gt;# CONFIG_PCI_MSI is not set&lt;br /&gt;CONFIG_PCI_LEGACY_PROC=y&lt;br /&gt;CONFIG_ISA_DMA_API=y&lt;br /&gt;# CONFIG_ISA is not set&lt;br /&gt;# CONFIG_MCA is not set&lt;br /&gt;# CONFIG_SCx200 is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# PCCARD (PCMCIA/CardBus) support&lt;br /&gt;#&lt;br /&gt;# CONFIG_PCCARD is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# PCI Hotplug Support&lt;br /&gt;#&lt;br /&gt;# CONFIG_HOTPLUG_PCI is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Executable file formats&lt;br /&gt;#&lt;br /&gt;CONFIG_BINFMT_ELF=y&lt;br /&gt;CONFIG_BINFMT_AOUT=y&lt;br /&gt;CONFIG_BINFMT_MISC=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Networking&lt;br /&gt;#&lt;br /&gt;CONFIG_NET=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Networking options&lt;br /&gt;#&lt;br /&gt;CONFIG_PACKET=y&lt;br /&gt;# CONFIG_PACKET_MMAP is not set&lt;br /&gt;CONFIG_UNIX=y&lt;br /&gt;# CONFIG_NET_KEY is not set&lt;br /&gt;CONFIG_INET=y&lt;br /&gt;CONFIG_IP_MULTICAST=y&lt;br /&gt;# CONFIG_IP_ADVANCED_ROUTER is not set&lt;br /&gt;CONFIG_IP_FIB_HASH=y&lt;br /&gt;# CONFIG_IP_PNP is not set&lt;br /&gt;# CONFIG_NET_IPIP is not set&lt;br /&gt;# CONFIG_NET_IPGRE is not set&lt;br /&gt;# CONFIG_IP_MROUTE is not set&lt;br /&gt;# CONFIG_ARPD is not set&lt;br /&gt;# CONFIG_SYN_COOKIES is not set&lt;br /&gt;# CONFIG_INET_AH is not set&lt;br /&gt;# CONFIG_INET_ESP is not set&lt;br /&gt;# CONFIG_INET_IPCOMP is not set&lt;br /&gt;# CONFIG_INET_TUNNEL is not set&lt;br /&gt;CONFIG_INET_DIAG=y&lt;br /&gt;CONFIG_INET_TCP_DIAG=y&lt;br /&gt;# CONFIG_TCP_CONG_ADVANCED is not set&lt;br /&gt;CONFIG_TCP_CONG_BIC=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# IP: Virtual Server Configuration&lt;br /&gt;#&lt;br /&gt;# CONFIG_IP_VS is not set&lt;br /&gt;# CONFIG_IPV6 is not set&lt;br /&gt;CONFIG_NETFILTER=y&lt;br /&gt;# CONFIG_NETFILTER_DEBUG is not set&lt;br /&gt;# CONFIG_NETFILTER_NETLINK is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# IP: Netfilter Configuration&lt;br /&gt;#&lt;br /&gt;CONFIG_IP_NF_CONNTRACK=y&lt;br /&gt;# CONFIG_IP_NF_CT_ACCT is not set&lt;br /&gt;# CONFIG_IP_NF_CONNTRACK_MARK is not set&lt;br /&gt;# CONFIG_IP_NF_CONNTRACK_EVENTS is not set&lt;br /&gt;# CONFIG_IP_NF_CT_PROTO_SCTP is not set&lt;br /&gt;# CONFIG_IP_NF_FTP is not set&lt;br /&gt;# CONFIG_IP_NF_IRC is not set&lt;br /&gt;# CONFIG_IP_NF_NETBIOS_NS is not set&lt;br /&gt;# CONFIG_IP_NF_TFTP is not set&lt;br /&gt;# CONFIG_IP_NF_AMANDA is not set&lt;br /&gt;# CONFIG_IP_NF_PPTP is not set&lt;br /&gt;CONFIG_IP_NF_QUEUE=y&lt;br /&gt;CONFIG_IP_NF_IPTABLES=y&lt;br /&gt;CONFIG_IP_NF_MATCH_LIMIT=y&lt;br /&gt;CONFIG_IP_NF_MATCH_IPRANGE=y&lt;br /&gt;CONFIG_IP_NF_MATCH_MAC=y&lt;br /&gt;CONFIG_IP_NF_MATCH_PKTTYPE=y&lt;br /&gt;CONFIG_IP_NF_MATCH_MARK=y&lt;br /&gt;CONFIG_IP_NF_MATCH_MULTIPORT=y&lt;br /&gt;CONFIG_IP_NF_MATCH_TOS=y&lt;br /&gt;CONFIG_IP_NF_MATCH_RECENT=y&lt;br /&gt;CONFIG_IP_NF_MATCH_ECN=y&lt;br /&gt;CONFIG_IP_NF_MATCH_DSCP=y&lt;br /&gt;CONFIG_IP_NF_MATCH_AH_ESP=y&lt;br /&gt;CONFIG_IP_NF_MATCH_LENGTH=y&lt;br /&gt;CONFIG_IP_NF_MATCH_TTL=y&lt;br /&gt;CONFIG_IP_NF_MATCH_TCPMSS=y&lt;br /&gt;CONFIG_IP_NF_MATCH_HELPER=y&lt;br /&gt;CONFIG_IP_NF_MATCH_STATE=y&lt;br /&gt;CONFIG_IP_NF_MATCH_CONNTRACK=y&lt;br /&gt;CONFIG_IP_NF_MATCH_OWNER=y&lt;br /&gt;# CONFIG_IP_NF_MATCH_ADDRTYPE is not set&lt;br /&gt;# CONFIG_IP_NF_MATCH_REALM is not set&lt;br /&gt;# CONFIG_IP_NF_MATCH_SCTP is not set&lt;br /&gt;# CONFIG_IP_NF_MATCH_DCCP is not set&lt;br /&gt;# CONFIG_IP_NF_MATCH_COMMENT is not set&lt;br /&gt;# CONFIG_IP_NF_MATCH_HASHLIMIT is not set&lt;br /&gt;# CONFIG_IP_NF_MATCH_STRING is not set&lt;br /&gt;CONFIG_IP_NF_FILTER=y&lt;br /&gt;CONFIG_IP_NF_TARGET_REJECT=y&lt;br /&gt;CONFIG_IP_NF_TARGET_LOG=y&lt;br /&gt;CONFIG_IP_NF_TARGET_ULOG=y&lt;br /&gt;CONFIG_IP_NF_TARGET_TCPMSS=y&lt;br /&gt;# CONFIG_IP_NF_TARGET_NFQUEUE is not set&lt;br /&gt;CONFIG_IP_NF_NAT=y&lt;br /&gt;CONFIG_IP_NF_NAT_NEEDED=y&lt;br /&gt;CONFIG_IP_NF_TARGET_MASQUERADE=y&lt;br /&gt;CONFIG_IP_NF_TARGET_REDIRECT=y&lt;br /&gt;CONFIG_IP_NF_TARGET_NETMAP=y&lt;br /&gt;CONFIG_IP_NF_TARGET_SAME=y&lt;br /&gt;# CONFIG_IP_NF_NAT_SNMP_BASIC is not set&lt;br /&gt;CONFIG_IP_NF_MANGLE=y&lt;br /&gt;CONFIG_IP_NF_TARGET_TOS=y&lt;br /&gt;CONFIG_IP_NF_TARGET_ECN=y&lt;br /&gt;CONFIG_IP_NF_TARGET_DSCP=y&lt;br /&gt;CONFIG_IP_NF_TARGET_MARK=y&lt;br /&gt;CONFIG_IP_NF_TARGET_CLASSIFY=y&lt;br /&gt;# CONFIG_IP_NF_TARGET_TTL is not set&lt;br /&gt;CONFIG_IP_NF_RAW=m&lt;br /&gt;CONFIG_IP_NF_TARGET_NOTRACK=m&lt;br /&gt;CONFIG_IP_NF_ARPTABLES=y&lt;br /&gt;CONFIG_IP_NF_ARPFILTER=y&lt;br /&gt;CONFIG_IP_NF_ARP_MANGLE=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# DCCP Configuration (EXPERIMENTAL)&lt;br /&gt;#&lt;br /&gt;# CONFIG_IP_DCCP is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# SCTP Configuration (EXPERIMENTAL)&lt;br /&gt;#&lt;br /&gt;# CONFIG_IP_SCTP is not set&lt;br /&gt;# CONFIG_ATM is not set&lt;br /&gt;# CONFIG_BRIDGE is not set&lt;br /&gt;# CONFIG_VLAN_8021Q is not set&lt;br /&gt;# CONFIG_DECNET is not set&lt;br /&gt;# CONFIG_LLC2 is not set&lt;br /&gt;# CONFIG_IPX is not set&lt;br /&gt;# CONFIG_ATALK is not set&lt;br /&gt;# CONFIG_X25 is not set&lt;br /&gt;# CONFIG_LAPB is not set&lt;br /&gt;# CONFIG_NET_DIVERT is not set&lt;br /&gt;# CONFIG_ECONET is not set&lt;br /&gt;# CONFIG_WAN_ROUTER is not set&lt;br /&gt;# CONFIG_NET_SCHED is not set&lt;br /&gt;# CONFIG_NET_CLS_ROUTE is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Network testing&lt;br /&gt;#&lt;br /&gt;# CONFIG_NET_PKTGEN is not set&lt;br /&gt;# CONFIG_HAMRADIO is not set&lt;br /&gt;# CONFIG_IRDA is not set&lt;br /&gt;# CONFIG_BT is not set&lt;br /&gt;# CONFIG_IEEE80211 is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Device Drivers&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Generic Driver Options&lt;br /&gt;#&lt;br /&gt;CONFIG_STANDALONE=y&lt;br /&gt;CONFIG_PREVENT_FIRMWARE_BUILD=y&lt;br /&gt;CONFIG_FW_LOADER=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Connector - unified userspace &lt;-&gt; kernelspace linker&lt;br /&gt;#&lt;br /&gt;# CONFIG_CONNECTOR is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Memory Technology Devices (MTD)&lt;br /&gt;#&lt;br /&gt;# CONFIG_MTD is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Parallel port support&lt;br /&gt;#&lt;br /&gt;CONFIG_PARPORT=y&lt;br /&gt;CONFIG_PARPORT_PC=y&lt;br /&gt;# CONFIG_PARPORT_SERIAL is not set&lt;br /&gt;# CONFIG_PARPORT_PC_FIFO is not set&lt;br /&gt;# CONFIG_PARPORT_PC_SUPERIO is not set&lt;br /&gt;# CONFIG_PARPORT_GSC is not set&lt;br /&gt;# CONFIG_PARPORT_1284 is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Plug and Play support&lt;br /&gt;#&lt;br /&gt;CONFIG_PNP=y&lt;br /&gt;# CONFIG_PNP_DEBUG is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Protocols&lt;br /&gt;#&lt;br /&gt;CONFIG_PNPACPI=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Block devices&lt;br /&gt;#&lt;br /&gt;CONFIG_BLK_DEV_FD=y&lt;br /&gt;# CONFIG_PARIDE is not set&lt;br /&gt;# CONFIG_BLK_CPQ_DA is not set&lt;br /&gt;# CONFIG_BLK_CPQ_CISS_DA is not set&lt;br /&gt;# CONFIG_BLK_DEV_DAC960 is not set&lt;br /&gt;# CONFIG_BLK_DEV_UMEM is not set&lt;br /&gt;# CONFIG_BLK_DEV_COW_COMMON is not set&lt;br /&gt;CONFIG_BLK_DEV_LOOP=y&lt;br /&gt;# CONFIG_BLK_DEV_CRYPTOLOOP is not set&lt;br /&gt;# CONFIG_BLK_DEV_NBD is not set&lt;br /&gt;# CONFIG_BLK_DEV_SX8 is not set&lt;br /&gt;# CONFIG_BLK_DEV_UB is not set&lt;br /&gt;# CONFIG_BLK_DEV_RAM is not set&lt;br /&gt;CONFIG_BLK_DEV_RAM_COUNT=16&lt;br /&gt;CONFIG_LBD=y&lt;br /&gt;CONFIG_CDROM_PKTCDVD=m&lt;br /&gt;CONFIG_CDROM_PKTCDVD_BUFFERS=8&lt;br /&gt;# CONFIG_CDROM_PKTCDVD_WCACHE is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# IO Schedulers&lt;br /&gt;#&lt;br /&gt;CONFIG_IOSCHED_NOOP=y&lt;br /&gt;CONFIG_IOSCHED_AS=y&lt;br /&gt;CONFIG_IOSCHED_DEADLINE=y&lt;br /&gt;CONFIG_IOSCHED_CFQ=y&lt;br /&gt;# CONFIG_ATA_OVER_ETH is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# ATA/ATAPI/MFM/RLL support&lt;br /&gt;#&lt;br /&gt;CONFIG_IDE=y&lt;br /&gt;CONFIG_BLK_DEV_IDE=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Please see Documentation/ide.txt for help/info on IDE drives&lt;br /&gt;#&lt;br /&gt;# CONFIG_BLK_DEV_IDE_SATA is not set&lt;br /&gt;# CONFIG_BLK_DEV_HD_IDE is not set&lt;br /&gt;CONFIG_BLK_DEV_IDEDISK=y&lt;br /&gt;CONFIG_IDEDISK_MULTI_MODE=y&lt;br /&gt;CONFIG_BLK_DEV_IDECD=y&lt;br /&gt;# CONFIG_BLK_DEV_IDETAPE is not set&lt;br /&gt;# CONFIG_BLK_DEV_IDEFLOPPY is not set&lt;br /&gt;# CONFIG_BLK_DEV_IDESCSI is not set&lt;br /&gt;# CONFIG_IDE_TASK_IOCTL is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# IDE chipset support/bugfixes&lt;br /&gt;#&lt;br /&gt;CONFIG_IDE_GENERIC=y&lt;br /&gt;CONFIG_BLK_DEV_CMD640=y&lt;br /&gt;# CONFIG_BLK_DEV_CMD640_ENHANCED is not set&lt;br /&gt;# CONFIG_BLK_DEV_IDEPNP is not set&lt;br /&gt;CONFIG_BLK_DEV_IDEPCI=y&lt;br /&gt;CONFIG_IDEPCI_SHARE_IRQ=y&lt;br /&gt;# CONFIG_BLK_DEV_OFFBOARD is not set&lt;br /&gt;CONFIG_BLK_DEV_GENERIC=y&lt;br /&gt;# CONFIG_BLK_DEV_OPTI621 is not set&lt;br /&gt;# CONFIG_BLK_DEV_RZ1000 is not set&lt;br /&gt;CONFIG_BLK_DEV_IDEDMA_PCI=y&lt;br /&gt;# CONFIG_BLK_DEV_IDEDMA_FORCED is not set&lt;br /&gt;CONFIG_IDEDMA_PCI_AUTO=y&lt;br /&gt;# CONFIG_IDEDMA_ONLYDISK is not set&lt;br /&gt;# CONFIG_BLK_DEV_AEC62XX is not set&lt;br /&gt;# CONFIG_BLK_DEV_ALI15X3 is not set&lt;br /&gt;# CONFIG_BLK_DEV_AMD74XX is not set&lt;br /&gt;# CONFIG_BLK_DEV_ATIIXP is not set&lt;br /&gt;# CONFIG_BLK_DEV_CMD64X is not set&lt;br /&gt;# CONFIG_BLK_DEV_TRIFLEX is not set&lt;br /&gt;# CONFIG_BLK_DEV_CY82C693 is not set&lt;br /&gt;# CONFIG_BLK_DEV_CS5520 is not set&lt;br /&gt;# CONFIG_BLK_DEV_CS5530 is not set&lt;br /&gt;# CONFIG_BLK_DEV_HPT34X is not set&lt;br /&gt;# CONFIG_BLK_DEV_HPT366 is not set&lt;br /&gt;# CONFIG_BLK_DEV_SC1200 is not set&lt;br /&gt;# CONFIG_BLK_DEV_PIIX is not set&lt;br /&gt;# CONFIG_BLK_DEV_IT821X is not set&lt;br /&gt;# CONFIG_BLK_DEV_NS87415 is not set&lt;br /&gt;# CONFIG_BLK_DEV_PDC202XX_OLD is not set&lt;br /&gt;# CONFIG_BLK_DEV_PDC202XX_NEW is not set&lt;br /&gt;# CONFIG_BLK_DEV_SVWKS is not set&lt;br /&gt;# CONFIG_BLK_DEV_SIIMAGE is not set&lt;br /&gt;CONFIG_BLK_DEV_SIS5513=y&lt;br /&gt;# CONFIG_BLK_DEV_SLC90E66 is not set&lt;br /&gt;# CONFIG_BLK_DEV_TRM290 is not set&lt;br /&gt;# CONFIG_BLK_DEV_VIA82CXXX is not set&lt;br /&gt;# CONFIG_IDE_ARM is not set&lt;br /&gt;CONFIG_BLK_DEV_IDEDMA=y&lt;br /&gt;# CONFIG_IDEDMA_IVB is not set&lt;br /&gt;CONFIG_IDEDMA_AUTO=y&lt;br /&gt;# CONFIG_BLK_DEV_HD is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# SCSI device support&lt;br /&gt;#&lt;br /&gt;# CONFIG_RAID_ATTRS is not set&lt;br /&gt;CONFIG_SCSI=y&lt;br /&gt;CONFIG_SCSI_PROC_FS=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# SCSI support type (disk, tape, CD-ROM)&lt;br /&gt;#&lt;br /&gt;CONFIG_BLK_DEV_SD=y&lt;br /&gt;# CONFIG_CHR_DEV_ST is not set&lt;br /&gt;# CONFIG_CHR_DEV_OSST is not set&lt;br /&gt;# CONFIG_BLK_DEV_SR is not set&lt;br /&gt;CONFIG_CHR_DEV_SG=y&lt;br /&gt;# CONFIG_CHR_DEV_SCH is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Some SCSI devices (e.g. CD jukebox) support multiple LUNs&lt;br /&gt;#&lt;br /&gt;# CONFIG_SCSI_MULTI_LUN is not set&lt;br /&gt;# CONFIG_SCSI_CONSTANTS is not set&lt;br /&gt;# CONFIG_SCSI_LOGGING is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# SCSI Transport Attributes&lt;br /&gt;#&lt;br /&gt;# CONFIG_SCSI_SPI_ATTRS is not set&lt;br /&gt;# CONFIG_SCSI_FC_ATTRS is not set&lt;br /&gt;# CONFIG_SCSI_ISCSI_ATTRS is not set&lt;br /&gt;# CONFIG_SCSI_SAS_ATTRS is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# SCSI low-level drivers&lt;br /&gt;#&lt;br /&gt;# CONFIG_BLK_DEV_3W_XXXX_RAID is not set&lt;br /&gt;# CONFIG_SCSI_3W_9XXX is not set&lt;br /&gt;# CONFIG_SCSI_ACARD is not set&lt;br /&gt;# CONFIG_SCSI_AACRAID is not set&lt;br /&gt;# CONFIG_SCSI_AIC7XXX is not set&lt;br /&gt;# CONFIG_SCSI_AIC7XXX_OLD is not set&lt;br /&gt;# CONFIG_SCSI_AIC79XX is not set&lt;br /&gt;CONFIG_SCSI_DPT_I2O=m&lt;br /&gt;# CONFIG_MEGARAID_NEWGEN is not set&lt;br /&gt;# CONFIG_MEGARAID_LEGACY is not set&lt;br /&gt;# CONFIG_MEGARAID_SAS is not set&lt;br /&gt;CONFIG_SCSI_SATA=y&lt;br /&gt;# CONFIG_SCSI_SATA_AHCI is not set&lt;br /&gt;# CONFIG_SCSI_SATA_SVW is not set&lt;br /&gt;CONFIG_SCSI_ATA_PIIX=y&lt;br /&gt;# CONFIG_SCSI_SATA_MV is not set&lt;br /&gt;# CONFIG_SCSI_SATA_NV is not set&lt;br /&gt;# CONFIG_SCSI_SATA_PROMISE is not set&lt;br /&gt;# CONFIG_SCSI_SATA_QSTOR is not set&lt;br /&gt;CONFIG_SCSI_SATA_SX4=m&lt;br /&gt;# CONFIG_SCSI_SATA_SIL is not set&lt;br /&gt;CONFIG_SCSI_SATA_SIS=m&lt;br /&gt;# CONFIG_SCSI_SATA_ULI is not set&lt;br /&gt;# CONFIG_SCSI_SATA_VIA is not set&lt;br /&gt;# CONFIG_SCSI_SATA_VITESSE is not set&lt;br /&gt;CONFIG_SCSI_SATA_INTEL_COMBINED=y&lt;br /&gt;# CONFIG_SCSI_BUSLOGIC is not set&lt;br /&gt;# CONFIG_SCSI_DMX3191D is not set&lt;br /&gt;# CONFIG_SCSI_EATA is not set&lt;br /&gt;# CONFIG_SCSI_FUTURE_DOMAIN is not set&lt;br /&gt;# CONFIG_SCSI_GDTH is not set&lt;br /&gt;# CONFIG_SCSI_IPS is not set&lt;br /&gt;# CONFIG_SCSI_INITIO is not set&lt;br /&gt;# CONFIG_SCSI_INIA100 is not set&lt;br /&gt;# CONFIG_SCSI_PPA is not set&lt;br /&gt;# CONFIG_SCSI_IMM is not set&lt;br /&gt;# CONFIG_SCSI_SYM53C8XX_2 is not set&lt;br /&gt;CONFIG_SCSI_IPR=m&lt;br /&gt;# CONFIG_SCSI_IPR_TRACE is not set&lt;br /&gt;# CONFIG_SCSI_IPR_DUMP is not set&lt;br /&gt;# CONFIG_SCSI_QLOGIC_FC is not set&lt;br /&gt;# CONFIG_SCSI_QLOGIC_1280 is not set&lt;br /&gt;CONFIG_SCSI_QLA2XXX=y&lt;br /&gt;# CONFIG_SCSI_QLA21XX is not set&lt;br /&gt;# CONFIG_SCSI_QLA22XX is not set&lt;br /&gt;# CONFIG_SCSI_QLA2300 is not set&lt;br /&gt;# CONFIG_SCSI_QLA2322 is not set&lt;br /&gt;# CONFIG_SCSI_QLA6312 is not set&lt;br /&gt;# CONFIG_SCSI_QLA24XX is not set&lt;br /&gt;# CONFIG_SCSI_LPFC is not set&lt;br /&gt;# CONFIG_SCSI_DC395x is not set&lt;br /&gt;# CONFIG_SCSI_DC390T is not set&lt;br /&gt;# CONFIG_SCSI_NSP32 is not set&lt;br /&gt;# CONFIG_SCSI_DEBUG is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Multi-device support (RAID and LVM)&lt;br /&gt;#&lt;br /&gt;# CONFIG_MD is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Fusion MPT device support&lt;br /&gt;#&lt;br /&gt;# CONFIG_FUSION is not set&lt;br /&gt;# CONFIG_FUSION_SPI is not set&lt;br /&gt;# CONFIG_FUSION_FC is not set&lt;br /&gt;# CONFIG_FUSION_SAS is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# IEEE 1394 (FireWire) support&lt;br /&gt;#&lt;br /&gt;# CONFIG_IEEE1394 is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# I2O device support&lt;br /&gt;#&lt;br /&gt;# CONFIG_I2O is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Network device support&lt;br /&gt;#&lt;br /&gt;CONFIG_NETDEVICES=y&lt;br /&gt;CONFIG_DUMMY=m&lt;br /&gt;# CONFIG_BONDING is not set&lt;br /&gt;# CONFIG_EQUALIZER is not set&lt;br /&gt;# CONFIG_TUN is not set&lt;br /&gt;# CONFIG_NET_SB1000 is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# ARCnet devices&lt;br /&gt;#&lt;br /&gt;# CONFIG_ARCNET is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# PHY device support&lt;br /&gt;#&lt;br /&gt;# CONFIG_PHYLIB is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Ethernet (10 or 100Mbit)&lt;br /&gt;#&lt;br /&gt;CONFIG_NET_ETHERNET=y&lt;br /&gt;CONFIG_MII=y&lt;br /&gt;# CONFIG_HAPPYMEAL is not set&lt;br /&gt;# CONFIG_SUNGEM is not set&lt;br /&gt;# CONFIG_CASSINI is not set&lt;br /&gt;# CONFIG_NET_VENDOR_3COM is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Tulip family network device support&lt;br /&gt;#&lt;br /&gt;# CONFIG_NET_TULIP is not set&lt;br /&gt;# CONFIG_HP100 is not set&lt;br /&gt;CONFIG_NET_PCI=y&lt;br /&gt;# CONFIG_PCNET32 is not set&lt;br /&gt;# CONFIG_AMD8111_ETH is not set&lt;br /&gt;# CONFIG_ADAPTEC_STARFIRE is not set&lt;br /&gt;# CONFIG_B44 is not set&lt;br /&gt;# CONFIG_FORCEDETH is not set&lt;br /&gt;# CONFIG_DGRS is not set&lt;br /&gt;# CONFIG_EEPRO100 is not set&lt;br /&gt;# CONFIG_E100 is not set&lt;br /&gt;# CONFIG_FEALNX is not set&lt;br /&gt;# CONFIG_NATSEMI is not set&lt;br /&gt;# CONFIG_NE2K_PCI is not set&lt;br /&gt;# CONFIG_8139CP is not set&lt;br /&gt;CONFIG_8139TOO=y&lt;br /&gt;CONFIG_8139TOO_PIO=y&lt;br /&gt;CONFIG_8139TOO_TUNE_TWISTER=y&lt;br /&gt;# CONFIG_8139TOO_8129 is not set&lt;br /&gt;# CONFIG_8139_OLD_RX_RESET is not set&lt;br /&gt;# CONFIG_SIS900 is not set&lt;br /&gt;# CONFIG_EPIC100 is not set&lt;br /&gt;# CONFIG_SUNDANCE is not set&lt;br /&gt;# CONFIG_TLAN is not set&lt;br /&gt;# CONFIG_VIA_RHINE is not set&lt;br /&gt;# CONFIG_NET_POCKET is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Ethernet (1000 Mbit)&lt;br /&gt;#&lt;br /&gt;# CONFIG_ACENIC is not set&lt;br /&gt;# CONFIG_DL2K is not set&lt;br /&gt;# CONFIG_E1000 is not set&lt;br /&gt;# CONFIG_NS83820 is not set&lt;br /&gt;# CONFIG_HAMACHI is not set&lt;br /&gt;# CONFIG_YELLOWFIN is not set&lt;br /&gt;# CONFIG_R8169 is not set&lt;br /&gt;# CONFIG_SIS190 is not set&lt;br /&gt;# CONFIG_SKGE is not set&lt;br /&gt;# CONFIG_SK98LIN is not set&lt;br /&gt;# CONFIG_VIA_VELOCITY is not set&lt;br /&gt;# CONFIG_TIGON3 is not set&lt;br /&gt;# CONFIG_BNX2 is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Ethernet (10000 Mbit)&lt;br /&gt;#&lt;br /&gt;# CONFIG_CHELSIO_T1 is not set&lt;br /&gt;# CONFIG_IXGB is not set&lt;br /&gt;# CONFIG_S2IO is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Token Ring devices&lt;br /&gt;#&lt;br /&gt;# CONFIG_TR is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Wireless LAN (non-hamradio)&lt;br /&gt;#&lt;br /&gt;CONFIG_NET_RADIO=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Obsolete Wireless cards support (pre-802.11)&lt;br /&gt;#&lt;br /&gt;# CONFIG_STRIP is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Wireless 802.11b ISA/PCI cards support&lt;br /&gt;#&lt;br /&gt;# CONFIG_AIRO is not set&lt;br /&gt;# CONFIG_HERMES is not set&lt;br /&gt;# CONFIG_ATMEL is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support&lt;br /&gt;#&lt;br /&gt;# CONFIG_PRISM54 is not set&lt;br /&gt;# CONFIG_HOSTAP is not set&lt;br /&gt;CONFIG_NET_WIRELESS=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Wan interfaces&lt;br /&gt;#&lt;br /&gt;# CONFIG_WAN is not set&lt;br /&gt;# CONFIG_FDDI is not set&lt;br /&gt;# CONFIG_HIPPI is not set&lt;br /&gt;# CONFIG_PLIP is not set&lt;br /&gt;# CONFIG_PPP is not set&lt;br /&gt;# CONFIG_SLIP is not set&lt;br /&gt;# CONFIG_NET_FC is not set&lt;br /&gt;# CONFIG_SHAPER is not set&lt;br /&gt;# CONFIG_NETCONSOLE is not set&lt;br /&gt;# CONFIG_NETPOLL is not set&lt;br /&gt;# CONFIG_NET_POLL_CONTROLLER is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# ISDN subsystem&lt;br /&gt;#&lt;br /&gt;# CONFIG_ISDN is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Telephony Support&lt;br /&gt;#&lt;br /&gt;# CONFIG_PHONE is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Input device support&lt;br /&gt;#&lt;br /&gt;CONFIG_INPUT=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Userland interfaces&lt;br /&gt;#&lt;br /&gt;CONFIG_INPUT_MOUSEDEV=y&lt;br /&gt;CONFIG_INPUT_MOUSEDEV_PSAUX=y&lt;br /&gt;CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024&lt;br /&gt;CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768&lt;br /&gt;# CONFIG_INPUT_JOYDEV is not set&lt;br /&gt;# CONFIG_INPUT_TSDEV is not set&lt;br /&gt;CONFIG_INPUT_EVDEV=m&lt;br /&gt;# CONFIG_INPUT_EVBUG is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Input Device Drivers&lt;br /&gt;#&lt;br /&gt;CONFIG_INPUT_KEYBOARD=y&lt;br /&gt;CONFIG_KEYBOARD_ATKBD=y&lt;br /&gt;# CONFIG_KEYBOARD_SUNKBD is not set&lt;br /&gt;# CONFIG_KEYBOARD_LKKBD is not set&lt;br /&gt;# CONFIG_KEYBOARD_XTKBD is not set&lt;br /&gt;# CONFIG_KEYBOARD_NEWTON is not set&lt;br /&gt;CONFIG_INPUT_MOUSE=y&lt;br /&gt;CONFIG_MOUSE_PS2=y&lt;br /&gt;# CONFIG_MOUSE_SERIAL is not set&lt;br /&gt;# CONFIG_MOUSE_VSXXXAA is not set&lt;br /&gt;# CONFIG_INPUT_JOYSTICK is not set&lt;br /&gt;# CONFIG_INPUT_TOUCHSCREEN is not set&lt;br /&gt;# CONFIG_INPUT_MISC is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Hardware I/O ports&lt;br /&gt;#&lt;br /&gt;CONFIG_SERIO=y&lt;br /&gt;CONFIG_SERIO_I8042=y&lt;br /&gt;# CONFIG_SERIO_SERPORT is not set&lt;br /&gt;# CONFIG_SERIO_CT82C710 is not set&lt;br /&gt;# CONFIG_SERIO_PARKBD is not set&lt;br /&gt;# CONFIG_SERIO_PCIPS2 is not set&lt;br /&gt;CONFIG_SERIO_LIBPS2=y&lt;br /&gt;# CONFIG_SERIO_RAW is not set&lt;br /&gt;# CONFIG_GAMEPORT is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Character devices&lt;br /&gt;#&lt;br /&gt;CONFIG_VT=y&lt;br /&gt;CONFIG_VT_CONSOLE=y&lt;br /&gt;CONFIG_HW_CONSOLE=y&lt;br /&gt;# CONFIG_SERIAL_NONSTANDARD is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Serial drivers&lt;br /&gt;#&lt;br /&gt;CONFIG_SERIAL_8250=y&lt;br /&gt;# CONFIG_SERIAL_8250_CONSOLE is not set&lt;br /&gt;# CONFIG_SERIAL_8250_ACPI is not set&lt;br /&gt;CONFIG_SERIAL_8250_NR_UARTS=4&lt;br /&gt;# CONFIG_SERIAL_8250_EXTENDED is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Non-8250 serial port support&lt;br /&gt;#&lt;br /&gt;CONFIG_SERIAL_CORE=y&lt;br /&gt;# CONFIG_SERIAL_JSM is not set&lt;br /&gt;CONFIG_UNIX98_PTYS=y&lt;br /&gt;CONFIG_LEGACY_PTYS=y&lt;br /&gt;CONFIG_LEGACY_PTY_COUNT=256&lt;br /&gt;CONFIG_PRINTER=y&lt;br /&gt;# CONFIG_LP_CONSOLE is not set&lt;br /&gt;# CONFIG_PPDEV is not set&lt;br /&gt;# CONFIG_TIPAR is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# IPMI&lt;br /&gt;#&lt;br /&gt;# CONFIG_IPMI_HANDLER is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Watchdog Cards&lt;br /&gt;#&lt;br /&gt;# CONFIG_WATCHDOG is not set&lt;br /&gt;# CONFIG_HW_RANDOM is not set&lt;br /&gt;# CONFIG_NVRAM is not set&lt;br /&gt;# CONFIG_RTC is not set&lt;br /&gt;# CONFIG_GEN_RTC is not set&lt;br /&gt;# CONFIG_DTLK is not set&lt;br /&gt;# CONFIG_R3964 is not set&lt;br /&gt;# CONFIG_APPLICOM is not set&lt;br /&gt;# CONFIG_SONYPI is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Ftape, the floppy tape device driver&lt;br /&gt;#&lt;br /&gt;# CONFIG_FTAPE is not set&lt;br /&gt;CONFIG_AGP=m&lt;br /&gt;# CONFIG_AGP_ALI is not set&lt;br /&gt;# CONFIG_AGP_ATI is not set&lt;br /&gt;# CONFIG_AGP_AMD is not set&lt;br /&gt;# CONFIG_AGP_AMD64 is not set&lt;br /&gt;CONFIG_AGP_INTEL=m&lt;br /&gt;# CONFIG_AGP_NVIDIA is not set&lt;br /&gt;CONFIG_AGP_SIS=m&lt;br /&gt;# CONFIG_AGP_SWORKS is not set&lt;br /&gt;# CONFIG_AGP_VIA is not set&lt;br /&gt;# CONFIG_AGP_EFFICEON is not set&lt;br /&gt;CONFIG_DRM=m&lt;br /&gt;# CONFIG_DRM_TDFX is not set&lt;br /&gt;# CONFIG_DRM_R128 is not set&lt;br /&gt;# CONFIG_DRM_RADEON is not set&lt;br /&gt;# CONFIG_DRM_I810 is not set&lt;br /&gt;# CONFIG_DRM_I830 is not set&lt;br /&gt;# CONFIG_DRM_I915 is not set&lt;br /&gt;# CONFIG_DRM_MGA is not set&lt;br /&gt;CONFIG_DRM_SIS=m&lt;br /&gt;# CONFIG_DRM_VIA is not set&lt;br /&gt;# CONFIG_DRM_SAVAGE is not set&lt;br /&gt;# CONFIG_MWAVE is not set&lt;br /&gt;# CONFIG_RAW_DRIVER is not set&lt;br /&gt;# CONFIG_HPET is not set&lt;br /&gt;# CONFIG_HANGCHECK_TIMER is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# TPM devices&lt;br /&gt;#&lt;br /&gt;# CONFIG_TCG_TPM is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# I2C support&lt;br /&gt;#&lt;br /&gt;CONFIG_I2C=y&lt;br /&gt;CONFIG_I2C_CHARDEV=m&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# I2C Algorithms&lt;br /&gt;#&lt;br /&gt;CONFIG_I2C_ALGOBIT=m&lt;br /&gt;CONFIG_I2C_ALGOPCF=m&lt;br /&gt;CONFIG_I2C_ALGOPCA=m&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# I2C Hardware Bus support&lt;br /&gt;#&lt;br /&gt;CONFIG_I2C_ALI1535=m&lt;br /&gt;CONFIG_I2C_ALI1563=m&lt;br /&gt;CONFIG_I2C_ALI15X3=m&lt;br /&gt;CONFIG_I2C_AMD756=m&lt;br /&gt;CONFIG_I2C_AMD756_S4882=m&lt;br /&gt;CONFIG_I2C_AMD8111=m&lt;br /&gt;CONFIG_I2C_I801=m&lt;br /&gt;CONFIG_I2C_I810=m&lt;br /&gt;CONFIG_I2C_PIIX4=m&lt;br /&gt;CONFIG_I2C_ISA=m&lt;br /&gt;CONFIG_I2C_NFORCE2=m&lt;br /&gt;CONFIG_I2C_PARPORT=m&lt;br /&gt;CONFIG_I2C_PARPORT_LIGHT=m&lt;br /&gt;CONFIG_I2C_PROSAVAGE=m&lt;br /&gt;CONFIG_I2C_SAVAGE4=m&lt;br /&gt;CONFIG_SCx200_ACB=m&lt;br /&gt;CONFIG_I2C_SIS5595=m&lt;br /&gt;CONFIG_I2C_SIS630=m&lt;br /&gt;CONFIG_I2C_SIS96X=m&lt;br /&gt;CONFIG_I2C_STUB=m&lt;br /&gt;CONFIG_I2C_VIA=m&lt;br /&gt;CONFIG_I2C_VIAPRO=m&lt;br /&gt;CONFIG_I2C_VOODOO3=m&lt;br /&gt;CONFIG_I2C_PCA_ISA=m&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Miscellaneous I2C Chip support&lt;br /&gt;#&lt;br /&gt;# CONFIG_SENSORS_DS1337 is not set&lt;br /&gt;# CONFIG_SENSORS_DS1374 is not set&lt;br /&gt;CONFIG_SENSORS_EEPROM=m&lt;br /&gt;# CONFIG_SENSORS_PCF8574 is not set&lt;br /&gt;# CONFIG_SENSORS_PCA9539 is not set&lt;br /&gt;# CONFIG_SENSORS_PCF8591 is not set&lt;br /&gt;# CONFIG_SENSORS_RTC8564 is not set&lt;br /&gt;# CONFIG_SENSORS_MAX6875 is not set&lt;br /&gt;# CONFIG_I2C_DEBUG_CORE is not set&lt;br /&gt;# CONFIG_I2C_DEBUG_ALGO is not set&lt;br /&gt;# CONFIG_I2C_DEBUG_BUS is not set&lt;br /&gt;# CONFIG_I2C_DEBUG_CHIP is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Dallas's 1-wire bus&lt;br /&gt;#&lt;br /&gt;# CONFIG_W1 is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Hardware Monitoring support&lt;br /&gt;#&lt;br /&gt;CONFIG_HWMON=y&lt;br /&gt;CONFIG_HWMON_VID=m&lt;br /&gt;# CONFIG_SENSORS_ADM1021 is not set&lt;br /&gt;# CONFIG_SENSORS_ADM1025 is not set&lt;br /&gt;# CONFIG_SENSORS_ADM1026 is not set&lt;br /&gt;# CONFIG_SENSORS_ADM1031 is not set&lt;br /&gt;# CONFIG_SENSORS_ADM9240 is not set&lt;br /&gt;# CONFIG_SENSORS_ASB100 is not set&lt;br /&gt;# CONFIG_SENSORS_ATXP1 is not set&lt;br /&gt;# CONFIG_SENSORS_DS1621 is not set&lt;br /&gt;# CONFIG_SENSORS_FSCHER is not set&lt;br /&gt;# CONFIG_SENSORS_FSCPOS is not set&lt;br /&gt;# CONFIG_SENSORS_GL518SM is not set&lt;br /&gt;# CONFIG_SENSORS_GL520SM is not set&lt;br /&gt;CONFIG_SENSORS_IT87=m&lt;br /&gt;# CONFIG_SENSORS_LM63 is not set&lt;br /&gt;# CONFIG_SENSORS_LM75 is not set&lt;br /&gt;# CONFIG_SENSORS_LM77 is not set&lt;br /&gt;# CONFIG_SENSORS_LM78 is not set&lt;br /&gt;# CONFIG_SENSORS_LM80 is not set&lt;br /&gt;# CONFIG_SENSORS_LM83 is not set&lt;br /&gt;# CONFIG_SENSORS_LM85 is not set&lt;br /&gt;# CONFIG_SENSORS_LM87 is not set&lt;br /&gt;# CONFIG_SENSORS_LM90 is not set&lt;br /&gt;# CONFIG_SENSORS_LM92 is not set&lt;br /&gt;# CONFIG_SENSORS_MAX1619 is not set&lt;br /&gt;# CONFIG_SENSORS_PC87360 is not set&lt;br /&gt;# CONFIG_SENSORS_SIS5595 is not set&lt;br /&gt;# CONFIG_SENSORS_SMSC47M1 is not set&lt;br /&gt;# CONFIG_SENSORS_SMSC47B397 is not set&lt;br /&gt;# CONFIG_SENSORS_VIA686A is not set&lt;br /&gt;# CONFIG_SENSORS_W83781D is not set&lt;br /&gt;# CONFIG_SENSORS_W83792D is not set&lt;br /&gt;# CONFIG_SENSORS_W83L785TS is not set&lt;br /&gt;# CONFIG_SENSORS_W83627HF is not set&lt;br /&gt;# CONFIG_SENSORS_W83627EHF is not set&lt;br /&gt;# CONFIG_SENSORS_HDAPS is not set&lt;br /&gt;# CONFIG_HWMON_DEBUG_CHIP is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Misc devices&lt;br /&gt;#&lt;br /&gt;# CONFIG_IBM_ASM is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Multimedia Capabilities Port drivers&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Multimedia devices&lt;br /&gt;#&lt;br /&gt;# CONFIG_VIDEO_DEV is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Digital Video Broadcasting Devices&lt;br /&gt;#&lt;br /&gt;# CONFIG_DVB is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Graphics support&lt;br /&gt;#&lt;br /&gt;CONFIG_FB=y&lt;br /&gt;CONFIG_FB_CFB_FILLRECT=y&lt;br /&gt;CONFIG_FB_CFB_COPYAREA=y&lt;br /&gt;CONFIG_FB_CFB_IMAGEBLIT=y&lt;br /&gt;CONFIG_FB_SOFT_CURSOR=y&lt;br /&gt;# CONFIG_FB_MACMODES is not set&lt;br /&gt;CONFIG_FB_MODE_HELPERS=y&lt;br /&gt;# CONFIG_FB_TILEBLITTING is not set&lt;br /&gt;# CONFIG_FB_CIRRUS is not set&lt;br /&gt;# CONFIG_FB_PM2 is not set&lt;br /&gt;# CONFIG_FB_CYBER2000 is not set&lt;br /&gt;# CONFIG_FB_ARC is not set&lt;br /&gt;# CONFIG_FB_ASILIANT is not set&lt;br /&gt;# CONFIG_FB_IMSTT is not set&lt;br /&gt;# CONFIG_FB_VGA16 is not set&lt;br /&gt;CONFIG_FB_VESA=y&lt;br /&gt;CONFIG_VIDEO_SELECT=y&lt;br /&gt;# CONFIG_FB_HGA is not set&lt;br /&gt;# CONFIG_FB_NVIDIA is not set&lt;br /&gt;# CONFIG_FB_RIVA is not set&lt;br /&gt;# CONFIG_FB_I810 is not set&lt;br /&gt;# CONFIG_FB_INTEL is not set&lt;br /&gt;# CONFIG_FB_MATROX is not set&lt;br /&gt;# CONFIG_FB_RADEON_OLD is not set&lt;br /&gt;# CONFIG_FB_RADEON is not set&lt;br /&gt;# CONFIG_FB_ATY128 is not set&lt;br /&gt;# CONFIG_FB_ATY is not set&lt;br /&gt;# CONFIG_FB_SAVAGE is not set&lt;br /&gt;# CONFIG_FB_SIS is not set&lt;br /&gt;# CONFIG_FB_NEOMAGIC is not set&lt;br /&gt;# CONFIG_FB_KYRO is not set&lt;br /&gt;# CONFIG_FB_3DFX is not set&lt;br /&gt;# CONFIG_FB_VOODOO1 is not set&lt;br /&gt;# CONFIG_FB_CYBLA is not set&lt;br /&gt;# CONFIG_FB_TRIDENT is not set&lt;br /&gt;# CONFIG_FB_GEODE is not set&lt;br /&gt;# CONFIG_FB_S1D13XXX is not set&lt;br /&gt;# CONFIG_FB_VIRTUAL is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Console display driver support&lt;br /&gt;#&lt;br /&gt;CONFIG_VGA_CONSOLE=y&lt;br /&gt;CONFIG_DUMMY_CONSOLE=y&lt;br /&gt;CONFIG_FRAMEBUFFER_CONSOLE=y&lt;br /&gt;# CONFIG_FONTS is not set&lt;br /&gt;CONFIG_FONT_8x8=y&lt;br /&gt;CONFIG_FONT_8x16=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Logo configuration&lt;br /&gt;#&lt;br /&gt;# CONFIG_LOGO is not set&lt;br /&gt;# CONFIG_BACKLIGHT_LCD_SUPPORT is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Sound&lt;br /&gt;#&lt;br /&gt;CONFIG_SOUND=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Advanced Linux Sound Architecture&lt;br /&gt;#&lt;br /&gt;CONFIG_SND=y&lt;br /&gt;CONFIG_SND_TIMER=y&lt;br /&gt;CONFIG_SND_PCM=y&lt;br /&gt;CONFIG_SND_SEQUENCER=y&lt;br /&gt;# CONFIG_SND_SEQ_DUMMY is not set&lt;br /&gt;CONFIG_SND_OSSEMUL=y&lt;br /&gt;CONFIG_SND_MIXER_OSS=y&lt;br /&gt;CONFIG_SND_PCM_OSS=y&lt;br /&gt;CONFIG_SND_SEQUENCER_OSS=y&lt;br /&gt;# CONFIG_SND_VERBOSE_PRINTK is not set&lt;br /&gt;# CONFIG_SND_DEBUG is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Generic devices&lt;br /&gt;#&lt;br /&gt;# CONFIG_SND_DUMMY is not set&lt;br /&gt;# CONFIG_SND_VIRMIDI is not set&lt;br /&gt;# CONFIG_SND_MTPAV is not set&lt;br /&gt;# CONFIG_SND_SERIAL_U16550 is not set&lt;br /&gt;# CONFIG_SND_MPU401 is not set&lt;br /&gt;CONFIG_SND_AC97_CODEC=y&lt;br /&gt;CONFIG_SND_AC97_BUS=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# PCI devices&lt;br /&gt;#&lt;br /&gt;# CONFIG_SND_ALI5451 is not set&lt;br /&gt;# CONFIG_SND_ATIIXP is not set&lt;br /&gt;# CONFIG_SND_ATIIXP_MODEM is not set&lt;br /&gt;# CONFIG_SND_AU8810 is not set&lt;br /&gt;# CONFIG_SND_AU8820 is not set&lt;br /&gt;# CONFIG_SND_AU8830 is not set&lt;br /&gt;# CONFIG_SND_AZT3328 is not set&lt;br /&gt;# CONFIG_SND_BT87X is not set&lt;br /&gt;# CONFIG_SND_CS46XX is not set&lt;br /&gt;# CONFIG_SND_CS4281 is not set&lt;br /&gt;# CONFIG_SND_EMU10K1 is not set&lt;br /&gt;# CONFIG_SND_EMU10K1X is not set&lt;br /&gt;# CONFIG_SND_CA0106 is not set&lt;br /&gt;# CONFIG_SND_KORG1212 is not set&lt;br /&gt;# CONFIG_SND_MIXART is not set&lt;br /&gt;# CONFIG_SND_NM256 is not set&lt;br /&gt;# CONFIG_SND_RME32 is not set&lt;br /&gt;# CONFIG_SND_RME96 is not set&lt;br /&gt;# CONFIG_SND_RME9652 is not set&lt;br /&gt;# CONFIG_SND_HDSP is not set&lt;br /&gt;# CONFIG_SND_HDSPM is not set&lt;br /&gt;# CONFIG_SND_TRIDENT is not set&lt;br /&gt;# CONFIG_SND_YMFPCI is not set&lt;br /&gt;# CONFIG_SND_AD1889 is not set&lt;br /&gt;# CONFIG_SND_ALS4000 is not set&lt;br /&gt;# CONFIG_SND_CMIPCI is not set&lt;br /&gt;# CONFIG_SND_ENS1370 is not set&lt;br /&gt;# CONFIG_SND_ENS1371 is not set&lt;br /&gt;# CONFIG_SND_ES1938 is not set&lt;br /&gt;# CONFIG_SND_ES1968 is not set&lt;br /&gt;# CONFIG_SND_MAESTRO3 is not set&lt;br /&gt;# CONFIG_SND_FM801 is not set&lt;br /&gt;# CONFIG_SND_ICE1712 is not set&lt;br /&gt;# CONFIG_SND_ICE1724 is not set&lt;br /&gt;CONFIG_SND_INTEL8X0=y&lt;br /&gt;CONFIG_SND_INTEL8X0M=y&lt;br /&gt;# CONFIG_SND_SONICVIBES is not set&lt;br /&gt;# CONFIG_SND_VIA82XX is not set&lt;br /&gt;# CONFIG_SND_VIA82XX_MODEM is not set&lt;br /&gt;# CONFIG_SND_VX222 is not set&lt;br /&gt;# CONFIG_SND_HDA_INTEL is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# USB devices&lt;br /&gt;#&lt;br /&gt;# CONFIG_SND_USB_AUDIO is not set&lt;br /&gt;# CONFIG_SND_USB_USX2Y is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Open Sound System&lt;br /&gt;#&lt;br /&gt;# CONFIG_SOUND_PRIME is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# USB support&lt;br /&gt;#&lt;br /&gt;CONFIG_USB_ARCH_HAS_HCD=y&lt;br /&gt;CONFIG_USB_ARCH_HAS_OHCI=y&lt;br /&gt;CONFIG_USB=y&lt;br /&gt;# CONFIG_USB_DEBUG is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Miscellaneous USB options&lt;br /&gt;#&lt;br /&gt;CONFIG_USB_DEVICEFS=y&lt;br /&gt;# CONFIG_USB_BANDWIDTH is not set&lt;br /&gt;# CONFIG_USB_DYNAMIC_MINORS is not set&lt;br /&gt;# CONFIG_USB_SUSPEND is not set&lt;br /&gt;# CONFIG_USB_OTG is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# USB Host Controller Drivers&lt;br /&gt;#&lt;br /&gt;CONFIG_USB_EHCI_HCD=y&lt;br /&gt;# CONFIG_USB_EHCI_SPLIT_ISO is not set&lt;br /&gt;# CONFIG_USB_EHCI_ROOT_HUB_TT is not set&lt;br /&gt;# CONFIG_USB_ISP116X_HCD is not set&lt;br /&gt;CONFIG_USB_OHCI_HCD=y&lt;br /&gt;# CONFIG_USB_OHCI_BIG_ENDIAN is not set&lt;br /&gt;CONFIG_USB_OHCI_LITTLE_ENDIAN=y&lt;br /&gt;# CONFIG_USB_UHCI_HCD is not set&lt;br /&gt;# CONFIG_USB_SL811_HCD is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# USB Device Class drivers&lt;br /&gt;#&lt;br /&gt;# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set&lt;br /&gt;# CONFIG_USB_BLUETOOTH_TTY is not set&lt;br /&gt;# CONFIG_USB_ACM is not set&lt;br /&gt;CONFIG_USB_PRINTER=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information&lt;br /&gt;#&lt;br /&gt;CONFIG_USB_STORAGE=y&lt;br /&gt;# CONFIG_USB_STORAGE_DEBUG is not set&lt;br /&gt;# CONFIG_USB_STORAGE_DATAFAB is not set&lt;br /&gt;# CONFIG_USB_STORAGE_FREECOM is not set&lt;br /&gt;# CONFIG_USB_STORAGE_ISD200 is not set&lt;br /&gt;# CONFIG_USB_STORAGE_DPCM is not set&lt;br /&gt;# CONFIG_USB_STORAGE_USBAT is not set&lt;br /&gt;# CONFIG_USB_STORAGE_SDDR09 is not set&lt;br /&gt;# CONFIG_USB_STORAGE_SDDR55 is not set&lt;br /&gt;# CONFIG_USB_STORAGE_JUMPSHOT is not set&lt;br /&gt;# CONFIG_USB_STORAGE_ONETOUCH is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# USB Input Devices&lt;br /&gt;#&lt;br /&gt;CONFIG_USB_HID=y&lt;br /&gt;CONFIG_USB_HIDINPUT=y&lt;br /&gt;# CONFIG_HID_FF is not set&lt;br /&gt;# CONFIG_USB_HIDDEV is not set&lt;br /&gt;# CONFIG_USB_AIPTEK is not set&lt;br /&gt;# CONFIG_USB_WACOM is not set&lt;br /&gt;# CONFIG_USB_ACECAD is not set&lt;br /&gt;# CONFIG_USB_KBTAB is not set&lt;br /&gt;# CONFIG_USB_POWERMATE is not set&lt;br /&gt;# CONFIG_USB_MTOUCH is not set&lt;br /&gt;# CONFIG_USB_ITMTOUCH is not set&lt;br /&gt;# CONFIG_USB_EGALAX is not set&lt;br /&gt;# CONFIG_USB_YEALINK is not set&lt;br /&gt;# CONFIG_USB_XPAD is not set&lt;br /&gt;# CONFIG_USB_ATI_REMOTE is not set&lt;br /&gt;# CONFIG_USB_KEYSPAN_REMOTE is not set&lt;br /&gt;# CONFIG_USB_APPLETOUCH is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# USB Imaging devices&lt;br /&gt;#&lt;br /&gt;# CONFIG_USB_MDC800 is not set&lt;br /&gt;# CONFIG_USB_MICROTEK is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# USB Multimedia devices&lt;br /&gt;#&lt;br /&gt;# CONFIG_USB_DABUSB is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Video4Linux support is needed for USB Multimedia device support&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# USB Network Adapters&lt;br /&gt;#&lt;br /&gt;# CONFIG_USB_CATC is not set&lt;br /&gt;# CONFIG_USB_KAWETH is not set&lt;br /&gt;# CONFIG_USB_PEGASUS is not set&lt;br /&gt;# CONFIG_USB_RTL8150 is not set&lt;br /&gt;# CONFIG_USB_USBNET is not set&lt;br /&gt;# CONFIG_USB_ZD1201 is not set&lt;br /&gt;CONFIG_USB_MON=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# USB port drivers&lt;br /&gt;#&lt;br /&gt;# CONFIG_USB_USS720 is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# USB Serial Converter support&lt;br /&gt;#&lt;br /&gt;# CONFIG_USB_SERIAL is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# USB Miscellaneous drivers&lt;br /&gt;#&lt;br /&gt;# CONFIG_USB_EMI62 is not set&lt;br /&gt;# CONFIG_USB_EMI26 is not set&lt;br /&gt;# CONFIG_USB_AUERSWALD is not set&lt;br /&gt;# CONFIG_USB_RIO500 is not set&lt;br /&gt;# CONFIG_USB_LEGOTOWER is not set&lt;br /&gt;# CONFIG_USB_LCD is not set&lt;br /&gt;# CONFIG_USB_LED is not set&lt;br /&gt;# CONFIG_USB_CYTHERM is not set&lt;br /&gt;# CONFIG_USB_PHIDGETKIT is not set&lt;br /&gt;# CONFIG_USB_PHIDGETSERVO is not set&lt;br /&gt;# CONFIG_USB_IDMOUSE is not set&lt;br /&gt;# CONFIG_USB_SISUSBVGA is not set&lt;br /&gt;# CONFIG_USB_LD is not set&lt;br /&gt;# CONFIG_USB_TEST is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# USB DSL modem support&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# USB Gadget Support&lt;br /&gt;#&lt;br /&gt;# CONFIG_USB_GADGET is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# MMC/SD Card support&lt;br /&gt;#&lt;br /&gt;# CONFIG_MMC is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# InfiniBand support&lt;br /&gt;#&lt;br /&gt;# CONFIG_INFINIBAND is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# SN Devices&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# File systems&lt;br /&gt;#&lt;br /&gt;CONFIG_EXT2_FS=y&lt;br /&gt;# CONFIG_EXT2_FS_XATTR is not set&lt;br /&gt;# CONFIG_EXT2_FS_XIP is not set&lt;br /&gt;CONFIG_EXT3_FS=y&lt;br /&gt;CONFIG_EXT3_FS_XATTR=y&lt;br /&gt;# CONFIG_EXT3_FS_POSIX_ACL is not set&lt;br /&gt;# CONFIG_EXT3_FS_SECURITY is not set&lt;br /&gt;CONFIG_JBD=y&lt;br /&gt;# CONFIG_JBD_DEBUG is not set&lt;br /&gt;CONFIG_FS_MBCACHE=y&lt;br /&gt;CONFIG_REISERFS_FS=y&lt;br /&gt;# CONFIG_REISERFS_CHECK is not set&lt;br /&gt;CONFIG_REISERFS_PROC_INFO=y&lt;br /&gt;# CONFIG_REISERFS_FS_XATTR is not set&lt;br /&gt;CONFIG_JFS_FS=m&lt;br /&gt;# CONFIG_JFS_POSIX_ACL is not set&lt;br /&gt;# CONFIG_JFS_SECURITY is not set&lt;br /&gt;# CONFIG_JFS_DEBUG is not set&lt;br /&gt;# CONFIG_JFS_STATISTICS is not set&lt;br /&gt;CONFIG_FS_POSIX_ACL=y&lt;br /&gt;CONFIG_XFS_FS=m&lt;br /&gt;# CONFIG_XFS_QUOTA is not set&lt;br /&gt;# CONFIG_XFS_SECURITY is not set&lt;br /&gt;# CONFIG_XFS_POSIX_ACL is not set&lt;br /&gt;# CONFIG_XFS_RT is not set&lt;br /&gt;# CONFIG_MINIX_FS is not set&lt;br /&gt;# CONFIG_ROMFS_FS is not set&lt;br /&gt;CONFIG_INOTIFY=y&lt;br /&gt;# CONFIG_QUOTA is not set&lt;br /&gt;CONFIG_DNOTIFY=y&lt;br /&gt;# CONFIG_AUTOFS_FS is not set&lt;br /&gt;# CONFIG_AUTOFS4_FS is not set&lt;br /&gt;# CONFIG_FUSE_FS is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# CD-ROM/DVD Filesystems&lt;br /&gt;#&lt;br /&gt;CONFIG_ISO9660_FS=y&lt;br /&gt;CONFIG_JOLIET=y&lt;br /&gt;# CONFIG_ZISOFS is not set&lt;br /&gt;CONFIG_UDF_FS=y&lt;br /&gt;CONFIG_UDF_NLS=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# DOS/FAT/NT Filesystems&lt;br /&gt;#&lt;br /&gt;CONFIG_FAT_FS=y&lt;br /&gt;CONFIG_MSDOS_FS=y&lt;br /&gt;CONFIG_VFAT_FS=y&lt;br /&gt;CONFIG_FAT_DEFAULT_CODEPAGE=437&lt;br /&gt;CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"&lt;br /&gt;CONFIG_NTFS_FS=y&lt;br /&gt;# CONFIG_NTFS_DEBUG is not set&lt;br /&gt;# CONFIG_NTFS_RW is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Pseudo filesystems&lt;br /&gt;#&lt;br /&gt;CONFIG_PROC_FS=y&lt;br /&gt;CONFIG_PROC_KCORE=y&lt;br /&gt;CONFIG_SYSFS=y&lt;br /&gt;CONFIG_TMPFS=y&lt;br /&gt;# CONFIG_HUGETLBFS is not set&lt;br /&gt;# CONFIG_HUGETLB_PAGE is not set&lt;br /&gt;CONFIG_RAMFS=y&lt;br /&gt;# CONFIG_RELAYFS_FS is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Miscellaneous filesystems&lt;br /&gt;#&lt;br /&gt;# CONFIG_ADFS_FS is not set&lt;br /&gt;# CONFIG_AFFS_FS is not set&lt;br /&gt;CONFIG_HFS_FS=y&lt;br /&gt;CONFIG_HFSPLUS_FS=y&lt;br /&gt;# CONFIG_BEFS_FS is not set&lt;br /&gt;# CONFIG_BFS_FS is not set&lt;br /&gt;# CONFIG_EFS_FS is not set&lt;br /&gt;# CONFIG_CRAMFS is not set&lt;br /&gt;# CONFIG_VXFS_FS is not set&lt;br /&gt;# CONFIG_HPFS_FS is not set&lt;br /&gt;# CONFIG_QNX4FS_FS is not set&lt;br /&gt;# CONFIG_SYSV_FS is not set&lt;br /&gt;# CONFIG_UFS_FS is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Network File Systems&lt;br /&gt;#&lt;br /&gt;CONFIG_NFS_FS=y&lt;br /&gt;CONFIG_NFS_V3=y&lt;br /&gt;CONFIG_NFS_V3_ACL=y&lt;br /&gt;CONFIG_NFS_V4=y&lt;br /&gt;# CONFIG_NFS_DIRECTIO is not set&lt;br /&gt;# CONFIG_NFSD is not set&lt;br /&gt;CONFIG_LOCKD=y&lt;br /&gt;CONFIG_LOCKD_V4=y&lt;br /&gt;CONFIG_NFS_ACL_SUPPORT=y&lt;br /&gt;CONFIG_NFS_COMMON=y&lt;br /&gt;CONFIG_SUNRPC=y&lt;br /&gt;CONFIG_SUNRPC_GSS=y&lt;br /&gt;CONFIG_RPCSEC_GSS_KRB5=y&lt;br /&gt;# CONFIG_RPCSEC_GSS_SPKM3 is not set&lt;br /&gt;# CONFIG_SMB_FS is not set&lt;br /&gt;# CONFIG_CIFS is not set&lt;br /&gt;# CONFIG_NCP_FS is not set&lt;br /&gt;# CONFIG_CODA_FS is not set&lt;br /&gt;# CONFIG_AFS_FS is not set&lt;br /&gt;# CONFIG_9P_FS is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Partition Types&lt;br /&gt;#&lt;br /&gt;# CONFIG_PARTITION_ADVANCED is not set&lt;br /&gt;CONFIG_MSDOS_PARTITION=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Native Language Support&lt;br /&gt;#&lt;br /&gt;CONFIG_NLS=y&lt;br /&gt;CONFIG_NLS_DEFAULT="iso8859-1"&lt;br /&gt;CONFIG_NLS_CODEPAGE_437=y&lt;br /&gt;# CONFIG_NLS_CODEPAGE_737 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_775 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_850 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_852 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_855 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_857 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_860 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_861 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_862 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_863 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_864 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_865 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_866 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_869 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_936 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_950 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_932 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_949 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_874 is not set&lt;br /&gt;# CONFIG_NLS_ISO8859_8 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_1250 is not set&lt;br /&gt;# CONFIG_NLS_CODEPAGE_1251 is not set&lt;br /&gt;# CONFIG_NLS_ASCII is not set&lt;br /&gt;CONFIG_NLS_ISO8859_1=y&lt;br /&gt;# CONFIG_NLS_ISO8859_2 is not set&lt;br /&gt;# CONFIG_NLS_ISO8859_3 is not set&lt;br /&gt;# CONFIG_NLS_ISO8859_4 is not set&lt;br /&gt;# CONFIG_NLS_ISO8859_5 is not set&lt;br /&gt;# CONFIG_NLS_ISO8859_6 is not set&lt;br /&gt;# CONFIG_NLS_ISO8859_7 is not set&lt;br /&gt;# CONFIG_NLS_ISO8859_9 is not set&lt;br /&gt;# CONFIG_NLS_ISO8859_13 is not set&lt;br /&gt;# CONFIG_NLS_ISO8859_14 is not set&lt;br /&gt;# CONFIG_NLS_ISO8859_15 is not set&lt;br /&gt;# CONFIG_NLS_KOI8_R is not set&lt;br /&gt;# CONFIG_NLS_KOI8_U is not set&lt;br /&gt;CONFIG_NLS_UTF8=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Profiling support&lt;br /&gt;#&lt;br /&gt;# CONFIG_PROFILING is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Kernel hacking&lt;br /&gt;#&lt;br /&gt;# CONFIG_PRINTK_TIME is not set&lt;br /&gt;# CONFIG_DEBUG_KERNEL is not set&lt;br /&gt;CONFIG_LOG_BUF_SHIFT=14&lt;br /&gt;CONFIG_DEBUG_BUGVERBOSE=y&lt;br /&gt;CONFIG_EARLY_PRINTK=y&lt;br /&gt;CONFIG_X86_FIND_SMP_CONFIG=y&lt;br /&gt;CONFIG_X86_MPPARSE=y&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Security options&lt;br /&gt;#&lt;br /&gt;# CONFIG_KEYS is not set&lt;br /&gt;# CONFIG_SECURITY is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Cryptographic options&lt;br /&gt;#&lt;br /&gt;CONFIG_CRYPTO=y&lt;br /&gt;CONFIG_CRYPTO_HMAC=y&lt;br /&gt;# CONFIG_CRYPTO_NULL is not set&lt;br /&gt;CONFIG_CRYPTO_MD4=y&lt;br /&gt;CONFIG_CRYPTO_MD5=y&lt;br /&gt;CONFIG_CRYPTO_SHA1=y&lt;br /&gt;CONFIG_CRYPTO_SHA256=y&lt;br /&gt;CONFIG_CRYPTO_SHA512=y&lt;br /&gt;CONFIG_CRYPTO_WP512=y&lt;br /&gt;CONFIG_CRYPTO_TGR192=y&lt;br /&gt;CONFIG_CRYPTO_DES=y&lt;br /&gt;CONFIG_CRYPTO_BLOWFISH=y&lt;br /&gt;CONFIG_CRYPTO_TWOFISH=y&lt;br /&gt;CONFIG_CRYPTO_SERPENT=y&lt;br /&gt;CONFIG_CRYPTO_AES_586=y&lt;br /&gt;CONFIG_CRYPTO_CAST5=y&lt;br /&gt;CONFIG_CRYPTO_CAST6=y&lt;br /&gt;CONFIG_CRYPTO_TEA=y&lt;br /&gt;CONFIG_CRYPTO_ARC4=y&lt;br /&gt;CONFIG_CRYPTO_KHAZAD=y&lt;br /&gt;CONFIG_CRYPTO_ANUBIS=y&lt;br /&gt;CONFIG_CRYPTO_DEFLATE=y&lt;br /&gt;CONFIG_CRYPTO_MICHAEL_MIC=y&lt;br /&gt;CONFIG_CRYPTO_CRC32C=y&lt;br /&gt;# CONFIG_CRYPTO_TEST is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Hardware crypto devices&lt;br /&gt;#&lt;br /&gt;# CONFIG_CRYPTO_DEV_PADLOCK is not set&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Library routines&lt;br /&gt;#&lt;br /&gt;# CONFIG_CRC_CCITT is not set&lt;br /&gt;# CONFIG_CRC16 is not set&lt;br /&gt;CONFIG_CRC32=y&lt;br /&gt;CONFIG_LIBCRC32C=y&lt;br /&gt;CONFIG_ZLIB_INFLATE=y&lt;br /&gt;CONFIG_ZLIB_DEFLATE=y&lt;br /&gt;CONFIG_GENERIC_HARDIRQS=y&lt;br /&gt;CONFIG_GENERIC_IRQ_PROBE=y&lt;br /&gt;CONFIG_X86_BIOS_REBOOT=y&lt;br /&gt;CONFIG_PC=y&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;font-weight:bold"&gt;X.org configuration: (X.Org 6.8.2)&lt;/span&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;Section "Module"&lt;br /&gt;    Load        "dbe"   # Double buffer extension&lt;br /&gt;&lt;br /&gt;# This loads the miscellaneous extensions module, and disables&lt;br /&gt;# initialisation of the XFree86-DGA extension within that module.&lt;br /&gt;#    SubSection  "extmod"&lt;br /&gt;#      Option    "omit xfree86-dga"   # don't initialise the DGA extension&lt;br /&gt;#    EndSubSection&lt;br /&gt;    Load        "type1"&lt;br /&gt;    Load        "freetype"&lt;br /&gt;    Load        "speedo"&lt;br /&gt;    Load  "truetype"&lt;br /&gt;&lt;br /&gt;# This loads the GLX module&lt;br /&gt;    Load       "glx"&lt;br /&gt;&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;# **********************************************************************&lt;br /&gt;# Files section.  This allows default font and rgb paths to be set&lt;br /&gt;# **********************************************************************&lt;br /&gt;&lt;br /&gt;Section "Files"&lt;br /&gt;&lt;br /&gt;    RgbPath "/usr/X11R6/lib/X11/rgb"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/local/"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/misc/:unscaled"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/75dpi/:unscaled"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/100dpi/:unscaled"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/TTF/"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/encodings/"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/util/"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/misc/"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/local/"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/Type1/"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/CID/"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/Speedo/"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/75dpi/"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/100dpi/"&lt;br /&gt;    FontPath   "/usr/X11R6/lib/X11/fonts/cyrillic/"&lt;br /&gt;    FontPath   "/usr/share/fonts/monotype/TrueType/"&lt;br /&gt;    FontPath   "/usr/share/fonts/artwiz/:unscaled"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "ServerFlags"&lt;br /&gt;&lt;br /&gt;#    Option     "NoTrapSignals"&lt;br /&gt;#    Option     "DontVTSwitch"&lt;br /&gt;#    Option     "DontZap"&lt;br /&gt;#    Option     "DontZoom"&lt;br /&gt;#    Option     "DisableVidModeExtension"&lt;br /&gt;#    Option     "AllowNonLocalXvidtune"&lt;br /&gt;#    Option     "DisableModInDev"&lt;br /&gt;#    Option     "AllowNonLocalModInDev"&lt;br /&gt;    Option      "blank time"    "10"    # 10 minutes&lt;br /&gt;&lt;br /&gt;#    Option      "standby time"  "20"&lt;br /&gt;#    Option      "suspend time"  "30"&lt;br /&gt;#    Option      "off time"      "60"&lt;br /&gt;&lt;br /&gt;# Option   "EstimateSizesAggresively" "0"&lt;br /&gt;&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;# **********************************************************************&lt;br /&gt;# Input devices&lt;br /&gt;# **********************************************************************&lt;br /&gt;&lt;br /&gt;# **********************************************************************&lt;br /&gt;# Core keyboard's InputDevice section&lt;br /&gt;# **********************************************************************&lt;br /&gt;&lt;br /&gt;Section "InputDevice"&lt;br /&gt;&lt;br /&gt;    Identifier "Keyboard1"&lt;br /&gt;    Driver "kbd"&lt;br /&gt;# For most OSs the protocol can be omitted (it defaults to "Standard").&lt;br /&gt;# When using XQUEUE (only for SVR3 and SVR4, but not Solaris),&lt;br /&gt;# uncomment the following line.&lt;br /&gt;&lt;br /&gt;#    Option     "Protocol"      "Xqueue"&lt;br /&gt;&lt;br /&gt;# Set the keyboard auto repeat parameters.  Not all platforms implement&lt;br /&gt;# this.&lt;br /&gt;&lt;br /&gt;#    Option     "AutoRepeat"    "500 5"&lt;br /&gt;&lt;br /&gt;# Specifiy which keyboard LEDs can be user-controlled (eg, with xset(1)).&lt;br /&gt;&lt;br /&gt;#    Option     "Xleds" "1 2 3"&lt;br /&gt;&lt;br /&gt;# To disable the XKEYBOARD extension, uncomment XkbDisable.&lt;br /&gt;&lt;br /&gt;#    Option     "XkbDisable"&lt;br /&gt;&lt;br /&gt;# To customise the XKB settings to suit your keyboard, modify the&lt;br /&gt;# lines below (which are the defaults).  For example, for a European&lt;br /&gt;# keyboard, you will probably want to use one of:&lt;br /&gt;#&lt;br /&gt;#    Option     "XkbModel"      "pc102"&lt;br /&gt;#    Option     "XkbModel"      "pc105"&lt;br /&gt;#&lt;br /&gt;# If you have a Microsoft Natural keyboard, you can use:&lt;br /&gt;#&lt;br /&gt;    Option     "XkbModel"      "microsoft"&lt;br /&gt;#&lt;br /&gt;# If you have a US "windows" keyboard you will want:&lt;br /&gt;#&lt;br /&gt;#    Option     "XkbModel"      "pc104"&lt;br /&gt;#&lt;br /&gt;# Then to change the language, change the Layout setting.&lt;br /&gt;# For example, a german layout can be obtained with:&lt;br /&gt;#&lt;br /&gt;#    Option     "XkbLayout"     "de"&lt;br /&gt;#&lt;br /&gt;# or:&lt;br /&gt;#&lt;br /&gt;#    Option     "XkbLayout"     "de"&lt;br /&gt;#    Option     "XkbVariant"    "nodeadkeys"&lt;br /&gt;#&lt;br /&gt;# If you'd like to switch the positions of your capslock and&lt;br /&gt;# control keys, use:&lt;br /&gt;#&lt;br /&gt;#    Option     "XkbOptions"    "ctrl:swapcaps"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# These are the default XKB settings for X.Org&lt;br /&gt;#&lt;br /&gt;#    Option     "XkbRules"      "xorg"&lt;br /&gt;#    Option     "XkbModel"      "pc101"&lt;br /&gt;#    Option     "XkbLayout"     "us"&lt;br /&gt;#    Option     "XkbVariant"    ""&lt;br /&gt;#    Option     "XkbOptions"    ""&lt;br /&gt;&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# **********************************************************************&lt;br /&gt;# Core Pointer's InputDevice section&lt;br /&gt;# **********************************************************************&lt;br /&gt;&lt;br /&gt;Section "InputDevice"&lt;br /&gt;&lt;br /&gt;# Identifier and driver&lt;br /&gt;&lt;br /&gt;    Identifier "Mouse1"&lt;br /&gt;    Driver "synaptics"&lt;br /&gt;    Option "Device"      "/dev/mouse"&lt;br /&gt;    Option "Protocol"    "auto-dev"&lt;br /&gt; Option "LeftEdge" "1700"&lt;br /&gt; Option "RightEdge" "5500"&lt;br /&gt; Option "TopEdge" "1700"&lt;br /&gt; Option "BottomEdge" "4200"&lt;br /&gt; Option "FingerLow" "25"&lt;br /&gt; Option "FingerHigh" "30"&lt;br /&gt; Option "MaxTapTime" "350"&lt;br /&gt; Option "MaxTapMove" "220"&lt;br /&gt; Option "VertScrollDelta" "100"&lt;br /&gt; Option "MinSpeed" "0.09"&lt;br /&gt; Option "MaxSpeed" "0.18"&lt;br /&gt; Option "AccelFactor" "0.0035"&lt;br /&gt; Option "SHMConfig" "on"&lt;br /&gt;# On platforms where PnP mouse detection is supported the following&lt;br /&gt;# protocol setting can be used when using a newer PnP mouse:&lt;br /&gt;&lt;br /&gt;#    Option     "Protocol"      "Auto"&lt;br /&gt;&lt;br /&gt;# The available mouse protocols types that you can set below are:&lt;br /&gt;#    Auto BusMouse GlidePoint GlidePointPS/2 IntelliMouse IMPS/2&lt;br /&gt;#    Logitech Microsoft MMHitTab MMSeries Mouseman MouseManPlusPS/2&lt;br /&gt;#    MouseSystems NetMousePS/2 NetScrollPS/2 OSMouse PS/2 SysMouse&lt;br /&gt;#    ThinkingMouse ThinkingMousePS/2 Xqueue&lt;br /&gt;&lt;br /&gt;# The mouse device.  The device is normally set to /dev/mouse,&lt;br /&gt;# which is usually a symbolic link to the real device.&lt;br /&gt;&lt;br /&gt;#   Option "Device"      "/dev/psaux"&lt;br /&gt;#   Option "Device"      "/dev/ttyS0"&lt;br /&gt;#   Option "Device"      "/dev/ttyS1"&lt;br /&gt;&lt;br /&gt;# When using XQUEUE, comment out the above two lines, and uncomment&lt;br /&gt;# the following line.&lt;br /&gt;&lt;br /&gt;#    Option "Protocol" "Xqueue"&lt;br /&gt;&lt;br /&gt;# Baudrate and SampleRate are only for some Logitech mice. In&lt;br /&gt;# almost every case these lines should be omitted.&lt;br /&gt;&lt;br /&gt;#    Option "BaudRate"  "9600"&lt;br /&gt;#    Option "SampleRate" "150"&lt;br /&gt;&lt;br /&gt;# Emulate3Buttons is an option for 2-button Microsoft mice&lt;br /&gt;# Emulate3Timeout is the timeout in milliseconds (default is 50ms)&lt;br /&gt;&lt;br /&gt;#    Option "Emulate3Buttons"&lt;br /&gt;#    Option "Emulate3Timeout"    "50"&lt;br /&gt;&lt;br /&gt;# ChordMiddle is an option for some 3-button Logitech mice&lt;br /&gt;&lt;br /&gt;#    Option "ChordMiddle"&lt;br /&gt;&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;# Some examples of extended input devices&lt;br /&gt;&lt;br /&gt;# Section "InputDevice"&lt;br /&gt;#    Identifier "spaceball"&lt;br /&gt;#    Driver     "magellan"&lt;br /&gt;#    Option     "Device"        "/dev/cua0"&lt;br /&gt;# EndSection&lt;br /&gt;#&lt;br /&gt;# Section "InputDevice"&lt;br /&gt;#    Identifier "spaceball2"&lt;br /&gt;#    Driver     "spaceorb"&lt;br /&gt;#    Option     "Device"        "/dev/cua0"&lt;br /&gt;# EndSection&lt;br /&gt;#&lt;br /&gt;# Section "InputDevice"&lt;br /&gt;#    Identifier "touchscreen0"&lt;br /&gt;#    Driver     "microtouch"&lt;br /&gt;#    Option     "Device"        "/dev/ttyS0"&lt;br /&gt;#    Option     "MinX"          "1412"&lt;br /&gt;#    Option     "MaxX"          "15184"&lt;br /&gt;#    Option     "MinY"          "15372"&lt;br /&gt;#    Option     "MaxY"          "1230"&lt;br /&gt;#    Option     "ScreenNumber"  "0"&lt;br /&gt;#    Option     "ReportingMode" "Scaled"&lt;br /&gt;#    Option     "ButtonNumber"  "1"&lt;br /&gt;#    Option     "SendCoreEvents"&lt;br /&gt;# EndSection&lt;br /&gt;#&lt;br /&gt;# Section "InputDevice"&lt;br /&gt;#    Identifier "touchscreen1"&lt;br /&gt;#    Driver     "elo2300"&lt;br /&gt;#    Option     "Device"        "/dev/ttyS0"&lt;br /&gt;#    Option     "MinX"          "231"&lt;br /&gt;#    Option     "MaxX"          "3868"&lt;br /&gt;#    Option     "MinY"          "3858"&lt;br /&gt;#    Option     "MaxY"          "272"&lt;br /&gt;#    Option     "ScreenNumber"  "0"&lt;br /&gt;#    Option     "ReportingMode" "Scaled"&lt;br /&gt;#    Option     "ButtonThreshold"       "17"&lt;br /&gt;#    Option     "ButtonNumber"  "1"&lt;br /&gt;#    Option     "SendCoreEvents"&lt;br /&gt;# EndSection&lt;br /&gt;&lt;br /&gt;# **********************************************************************&lt;br /&gt;# Monitor section&lt;br /&gt;# **********************************************************************&lt;br /&gt;&lt;br /&gt;# Any number of monitor sections may be present&lt;br /&gt;&lt;br /&gt;Section "Monitor"&lt;br /&gt;&lt;br /&gt;    Identifier  "My Monitor"&lt;br /&gt;&lt;br /&gt;# HorizSync is in kHz unless units are specified.&lt;br /&gt;# HorizSync may be a comma separated list of discrete values, or a&lt;br /&gt;# comma separated list of ranges of values.&lt;br /&gt;# NOTE: THE VALUES HERE ARE EXAMPLES ONLY.  REFER TO YOUR MONITOR'S&lt;br /&gt;# USER MANUAL FOR THE CORRECT NUMBERS.&lt;br /&gt;&lt;br /&gt;    HorizSync   31.5 - 50.0&lt;br /&gt;&lt;br /&gt;#    HorizSync 30-64         # multisync&lt;br /&gt;#    HorizSync 31.5, 35.2    # multiple fixed sync frequencies&lt;br /&gt;#    HorizSync 15-25, 30-50  # multiple ranges of sync frequencies&lt;br /&gt;&lt;br /&gt;# VertRefresh is in Hz unless units are specified.&lt;br /&gt;# VertRefresh may be a comma separated list of discrete values, or a&lt;br /&gt;# comma separated list of ranges of values.&lt;br /&gt;# NOTE: THE VALUES HERE ARE EXAMPLES ONLY.  REFER TO YOUR MONITOR'S&lt;br /&gt;# USER MANUAL FOR THE CORRECT NUMBERS.&lt;br /&gt;&lt;br /&gt;    VertRefresh 40-90&lt;br /&gt;&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# **********************************************************************&lt;br /&gt;# Graphics device section&lt;br /&gt;# **********************************************************************&lt;br /&gt;&lt;br /&gt;# Any number of graphics device sections may be present&lt;br /&gt;&lt;br /&gt;Section "Device"&lt;br /&gt;    Identifier  "VESA Framebuffer"&lt;br /&gt;    Driver      "vesa"&lt;br /&gt;    #VideoRam    4096&lt;br /&gt;    # Insert Clocks lines here if appropriate&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "Device"&lt;br /&gt; Identifier "sis"&lt;br /&gt; Driver "sis"&lt;br /&gt; Option "DRI" "on"&lt;br /&gt; Option "AGPSize" "32"&lt;br /&gt;&lt;br /&gt;EndSection&lt;br /&gt;# **********************************************************************&lt;br /&gt;# Screen sections&lt;br /&gt;# **********************************************************************&lt;br /&gt;&lt;br /&gt;# Any number of screen sections may be present.  Each describes&lt;br /&gt;# the configuration of a single screen.  A single specific screen section&lt;br /&gt;# may be specified from the X server command line with the "-screen"&lt;br /&gt;# option.&lt;br /&gt;Section "Screen"&lt;br /&gt;    Identifier  "Screen 1"&lt;br /&gt;    Device      "sis"&lt;br /&gt;    Monitor     "My Monitor"&lt;br /&gt;&lt;br /&gt;# If your card can handle it, a higher default color depth (like 24 or 32)&lt;br /&gt;# is highly recommended.&lt;br /&gt;&lt;br /&gt;#   DefaultDepth 8&lt;br /&gt;#   DefaultDepth 16&lt;br /&gt;   DefaultDepth 24&lt;br /&gt;#   DefaultDepth 32&lt;br /&gt;&lt;br /&gt;# "1024x768" is also a conservative usable default resolution.  If you&lt;br /&gt;# have a better monitor, feel free to try resolutions such as&lt;br /&gt;# "1152x864", "1280x1024", "1600x1200", and "1800x1400" (or whatever your&lt;br /&gt;# card/monitor can produce)&lt;br /&gt;&lt;br /&gt;    Subsection "Display"&lt;br /&gt;        Depth       8&lt;br /&gt;        Modes "1024x768" "800x600" "640x480"&lt;br /&gt;    EndSubsection&lt;br /&gt;    Subsection "Display"&lt;br /&gt;        Depth       16&lt;br /&gt;        Modes "1024x768" "800x600" "640x480"&lt;br /&gt;    EndSubsection&lt;br /&gt;    Subsection "Display"&lt;br /&gt;        Depth       24&lt;br /&gt;        Modes "1024x768" "800x600" "640x480"&lt;br /&gt;    EndSubsection&lt;br /&gt;    Subsection "Display"&lt;br /&gt;        Depth       32&lt;br /&gt;        Modes "1024x768" "800x600" "640x480"&lt;br /&gt;    EndSubsection&lt;br /&gt;&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "InputDevice"&lt;br /&gt; Identifier "Mouse2"&lt;br /&gt; Driver "mouse"&lt;br /&gt; Option "Protocol" "IMPS/2"&lt;br /&gt; Option "Device" "/dev/input/mouse0"&lt;br /&gt; Option "ZAxisMapping" "4 5"&lt;br /&gt; Option "Buttons" "5"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "ServerLayout"&lt;br /&gt;# The Identifier line must be present&lt;br /&gt;    Identifier  "Simple Layout"&lt;br /&gt;    Screen "Screen 1"&lt;br /&gt;    #InputDevice "Mouse1" "CorePointer"&lt;br /&gt;    InputDevice "Keyboard1" "CoreKeyboard"&lt;br /&gt;    #InputDevice "Mouse2" "AlwaysCore"&lt;br /&gt;    InputDevice "Mouse1"&lt;br /&gt;    InputDevice "Mouse2"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And that's pretty much everything you need to get running... On top of that, you should also not that lm_sensors doesn't properly detect the hardware. I haven't got this working perfectly yet, but here's my /etc/sensors.conf file:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;# The following is for the Inside Technologies 786LCD which uses either a&lt;br /&gt;# IT8705F or a SIS950 for monitoring with the SIS630.&lt;br /&gt;# You will need to load the it87 module as follows to select the correct&lt;br /&gt;# temperature sensor type.&lt;br /&gt;# modprobe it87 temp_type=0x31&lt;br /&gt;# The sensors-detect program reports lm78 and a sis5595 and lists the it87 as&lt;br /&gt;# a misdetect.  Don't do the modprobe for the lm78 or sis5595 as suggested.&lt;br /&gt;#&lt;br /&gt;# delete or comment out above it87 section and uncomment the following.&lt;br /&gt;chip "it87-*"&lt;br /&gt;    label in0 "VCore 1"&lt;br /&gt;    label in1 "VCore 2"&lt;br /&gt;    label in2 "+3.3V"&lt;br /&gt;    label in3 "+5V"&lt;br /&gt;    label in4 "+12V"&lt;br /&gt;    label in5 "3.3 Stdby"&lt;br /&gt;    label in6 "-12V"&lt;br /&gt;    label in7 "Stdby"&lt;br /&gt;    label in8 "VBat"&lt;br /&gt;   # in0 will depend on your processor VID value, set to voltage specified in&lt;br /&gt;    # bios setup screen&lt;br /&gt;    set in0_min 1.7 * 0.95&lt;br /&gt;    set in0_max 1.7 * 1.05&lt;br /&gt;    set in1_min 2.4&lt;br /&gt;    set in1_max 2.6&lt;br /&gt;    set in2_min 3.3 * 0.95&lt;br /&gt;    set in2_max 3.3 * 1.05&lt;br /&gt;    set in3_min 5.0 * 0.95&lt;br /&gt;    set in3_max 5.0 * 1.05&lt;br /&gt;    # +- 12V are very poor tolerance on this board. Verified with voltmeter&lt;br /&gt;    set in4_min 12 * 0.90&lt;br /&gt;    set in4_max 12 * 1.10&lt;br /&gt;    set in5_min 3.3 * 0.95&lt;br /&gt;    set in5_max 3.3 * 1.05&lt;br /&gt;    set in6_max -12 * 0.90&lt;br /&gt;    set in6_min -12 * 1.10&lt;br /&gt;    set in7_min 5 * 0.95&lt;br /&gt;    set in7_max 5 * 1.05&lt;br /&gt;    # vid not monitored by IT8705F&lt;br /&gt;#    ignore  vid&lt;br /&gt;&lt;br /&gt;    compute in3 ((6.8/10)+1)*@ ,  @/((6.8/10)+1)&lt;br /&gt;    compute in4 ((30/10) +1)*@  , @/((30/10) +1)&lt;br /&gt;    compute in6 (1+232/56)*@ - 4.096*232/56, (@ + 4.096*232/56)/(1+232/56)&lt;br /&gt;    compute in7 ((6.8/10)+1)*@ ,  @/((6.8/10)+1)&lt;br /&gt;    # Temperature&lt;br /&gt;    label temp1       "CPU Temp"&lt;br /&gt;    ignore temp2&lt;br /&gt;    ignore temp3&lt;br /&gt;    # Fans&lt;br /&gt;    set fan1_min 3000&lt;br /&gt;#    ignore fan2&lt;br /&gt;#    ignore fan3&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-113353177068353735?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/113353177068353735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=113353177068353735' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113353177068353735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113353177068353735'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/12/balance-cn6555-notebook-slackware_02.html' title='Balance CN6555 Notebook - Slackware'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-113323777547648055</id><published>2005-11-28T21:03:00.000-07:00</published><updated>2006-11-15T21:19:48.176-07:00</updated><title type='text'>A new laptop for linux!</title><content type='html'>Hello everyone,&lt;br /&gt;&lt;br /&gt;I've been working on my HP ze4420us for a while now. I've got several posts regarding it, but things may very well change. My father purchased a laptop from Walmart a little while ago, and decided that since I'm the one who uses my computer for big projects all the time, he'd let me keep the new one if I gave him my old one. Great, right?&lt;br /&gt;&lt;br /&gt;The only problem is that I remember my experiences setting up linux on this laptop (HP), and don't want to go through that month-long process again. So far though, I've spent only a few hours, and already have wireless support (rt2500, which offers better support than any linksys wireless card :)), and all of my settings copied over... In addition, the new laptop sports the fancy USB2.0, which might come in handy if my christmas gift is that of an electronic music device (wink, wink), and four of them at that. The processor is an Intel, and not an AMD, which gets me kind of messed up inside, but it's got double the L2 cache, a higher FSB (400mhz), although 200mhz less clock speed. The HP's got a quiet keyboard, and a case that doesn't seem like it's going to break when I pick it up, and the touchpad is much larger and, in my opinion, easier to use. I'm still working on the proper kernel compilation for the new computer, but it doesn't seem like the SiS graphics card works as well as the ATI IGP card in the HP. &lt;br /&gt;&lt;br /&gt;Since there's no guide for linux installation on the linux on laptops site for this model computer, I'll probably put one up when I'm done... I still have to make the decision though, and wish I could keep both... Next year I'm working for a powerbook.&lt;br /&gt;&lt;br /&gt;'Till next time,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-113323777547648055?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/113323777547648055/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=113323777547648055' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113323777547648055'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113323777547648055'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/11/new-laptop-for-linux.html' title='A new laptop for linux!'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-113261193622357213</id><published>2005-11-21T15:06:00.000-07:00</published><updated>2006-11-15T21:19:48.091-07:00</updated><title type='text'>Executing programs as root from X</title><content type='html'>Hey everyone,&lt;br /&gt;&lt;br /&gt;So I've got this linux box set up nicely. The cd-rom read is allowed by all users, but cd-rom write is allowed only by root. For the past 10 minutes I've been browsing the net trying to figure out a way to execute my cd-burning software as root. I knew about a few solutions, but here's why I decided not to use them:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;sudo&lt;/b&gt;&lt;br /&gt;We all do it. We have a very strong superuser password, but very weak (or at least somewhat weaker) user passwords. Allowing access to the program with sudo by my user would be a very bad idea, because if somebody was able to crack my weak user password (possible), they'd have unrestricted access to those programs which you didn't want them to in the first place.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Altered permissions&lt;/b&gt;&lt;br /&gt;See above.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;consolehelper&lt;/b&gt;&lt;br /&gt;This is truly a nifty little application, and I've used it before. My issue is pam. I don't think that managing a system via simple UNIX permissions is a bad thing, and I don't believe that there is a need to use pam. Consolehelper does. If I were to use consolehelper, I'd have to install PAM, and that's just out of the question at the moment. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;su via terminal&lt;/b&gt;&lt;br /&gt;At first I didn't want to do this... It just seemed a little too close to what I've already been doing, and I thought it wouldn't work as well as I wanted. But guess what:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;su -c gnomebaker&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Works extremely well... Here's a screenshot:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/screenshot.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/screenshot.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now, that's not really what I was worried about getting done right. What I didn't want to do was close two windows after gnomebaker was exited. Thankfully, (tested with fluxbox only), the aterm closes as well. &lt;br /&gt;&lt;br /&gt;So for now, that's my solution. What I'll probably end up doing is writing a very simple GTK login form similar to what consolehleper does, but that's for another day. Right now this works just fine...&lt;br /&gt;&lt;br /&gt;BTW: I'd just like to let all the other geeks that read this know what I think about Sony BMG... Ha. Nevermind. Let's just say that as I geek you already know what I think.&lt;br /&gt;&lt;br /&gt;Till next time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-113261193622357213?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/113261193622357213/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=113261193622357213' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113261193622357213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113261193622357213'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/11/executing-programs-as-root-from-x.html' title='Executing programs as root from X'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-113091334519202465</id><published>2005-11-01T23:30:00.000-07:00</published><updated>2006-11-15T21:19:48.007-07:00</updated><title type='text'>What to do in prison...</title><content type='html'>So... A quick post, something that obviously crosses the mind of most of us non-hispanic non-aryan-white white people... We're the minority in prisons, so what do we do? &lt;br /&gt;&lt;br /&gt;Sample minority groups:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;English&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Australian&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Persian&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Arab&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Jewish&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Anybody have any statistics and such?&lt;br /&gt;&lt;br /&gt;Good day,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-113091334519202465?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/113091334519202465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=113091334519202465' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113091334519202465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/113091334519202465'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/11/what-to-do-in-prison.html' title='What to do in prison...'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112972788708951699</id><published>2005-10-19T05:44:00.000-07:00</published><updated>2006-11-15T21:19:47.911-07:00</updated><title type='text'>Gentoo Update</title><content type='html'>So I've finally gotten a few things done with Gentoo! My system is in the process of installing PHP5 on top of my mysql and apache2 installations... Hopefully everything will go well..&lt;br /&gt;&lt;br /&gt;I think that the gentoo system is a pretty amazing distro. Portage, although quite difficult to get working properly at the moment, seems to be something I'll end up loving in the future. I use the KDE desktop, and I like to have things looking pretty good, so I decided I needed the taskbar v2, which allows the taskbar to be fully transparent. I try an emerge --search, and then an emerge --searchdesc to try to find the ebuild for this software, and failed. I couldn't find an e-build anywhere, and that put me in a very strange place. (I've been up now for over 50 hours, probably around 42 when I ran into this problem). How can I get this software installed? I figured a ./configure &amp;&amp; make &amp;&amp; make install wasn't the appropriate thing to do on a gentoo installation, and after about 30 minutes of research figured out my only solution would be an ebuild. Now remember, I have not yet attempted to actually figure out the portage system. I vimmed up the skeleton ebuild and started editing. In the end I got something like this:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;# Copyright 1999-2005 Gentoo Foundation&lt;br /&gt;# Distributed under the terms of the GNU General Public License v2&lt;br /&gt;# $Header: $&lt;br /&gt;&lt;br /&gt;inherit kde eutils&lt;br /&gt;DESCRIPTION="Taskbar v2 - allows transparency in the taskbar. "&lt;br /&gt;HOMEPAGE="http://www.uni-weimar.de/~wolff3/index_taskbar.html"&lt;br /&gt;&lt;br /&gt;# http://www.uni-weimar.de/~wolff3/kdelook/mtaskbar-0.7.tar.bz2&lt;br /&gt;SRC_URI="http://www.uni-weimar.de/~wolff3/kdelook/${P}.tar.bz2"&lt;br /&gt;&lt;br /&gt;#I'm not distributing the .ebuild, and I didn't actually look up &lt;br /&gt;#licence of mtaskbar, sorry. &lt;br /&gt;LICENSE="gpl"&lt;br /&gt;&lt;br /&gt;SLOT="0"&lt;br /&gt;&lt;br /&gt;KEYWORDS="~x86 ~i686"&lt;br /&gt;IUSE=""&lt;br /&gt;&lt;br /&gt;DEPEND=""&lt;br /&gt;&lt;br /&gt;S=${WORKDIR}/${P}/${PN}&lt;br /&gt;#I had to figure out how this works, since the source didn't extract in a &lt;br /&gt;# normal way:&lt;br /&gt;#echo ${WORKDIR}/${P}/${PN}&lt;br /&gt;&lt;br /&gt;src_compile() {&lt;br /&gt; econf || die "econf failed"&lt;br /&gt; emake || die "emake failed"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;src_install() {&lt;br /&gt; make DESTDIR=${D} install || die&lt;br /&gt; #einstall || die&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And I know it's probably the ugliest thing an experienced gentoo user has ever seen, but guess what? It works! I finally have a nice desktop with the transparent titlebar!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/snapshot1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/snapshot1.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So I've still got to set up my openssl stuff with apache, and really need to recompile my kernel for iptables (don't believe I forgot to do that). But I've got wireless up and running, and my desktop pretty much the way I want it. Welcome Gentoo!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112972788708951699?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112972788708951699/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112972788708951699' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112972788708951699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112972788708951699'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/10/gentoo-update.html' title='Gentoo Update'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112955262954284838</id><published>2005-10-17T05:28:00.000-07:00</published><updated>2006-11-15T21:19:47.839-07:00</updated><title type='text'>Slackware to Gentoo... in process</title><content type='html'>Hello everyone... I'm back, at least for now. I've got an issue with my laptop hard drive, which continues to fail. There are loads of bad blocks, and new ones popping up all the time, causing hell. I recently had a corruption problem that knocked out my local apache installation, and not actually knowing anything about ReiserFS, I decided I'd just re-install it. So, there I go...&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;rm -rf /...&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;When BAM! I hit my enter key accidentally. Ctrl-C ends the destructive process just a little to late. I manage to keep a few utilities (enough to get stuff backed up onto CD, interesting without ls and cdrecord), and decide it's probably time for a change anyway. So I hit up the Gentoo web site on Knoppix, download the gentoo minimal install CD, and get to work. &lt;br /&gt;&lt;br /&gt;I must say... Gentoo is a pretty cool system so far, but it has taken forever to get where I'm at right now! I have fluxbox running with firefox, a KDE emerge and mplayer emerge occuring right now (should have gotten alsautils emerged first, but what the heck), a kernel compiled properly except for one setting (for my wireless), and a pretty fast freaking system. I decided to use a stage1 snapshot, and its day 4 so far. I just hope it's all worth it.&lt;br /&gt;&lt;br /&gt;This is going to be quite a change from my normal ./configure &amp;&amp; make &amp;&amp; checkinstall process, but I think that it will probably be a little easier to keep track of dependencies this way... Besides, the portage experience should help me out if I ever want to switch to a *BSD system...&lt;br /&gt;&lt;br /&gt;I'll be back at a later time (much later probably), once I get this distro up and running perfectly...&lt;br /&gt;&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112955262954284838?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112955262954284838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112955262954284838' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112955262954284838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112955262954284838'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/10/slackware-to-gentoo-in-process.html' title='Slackware to Gentoo... in process'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112740163637156077</id><published>2005-09-22T07:44:00.000-07:00</published><updated>2006-11-15T21:19:47.762-07:00</updated><title type='text'>Programming for Paypal</title><content type='html'>Yep. I'm back. Again after a little while. I just don't have all that much to give anybody yet, and don't like coming up here and writing when I have nothing interesting to say.&lt;br /&gt;&lt;br /&gt;Before I begin bitching, let me first start on a lighter note. I've switched from PHPEclipse to Quanta for my PHP/HTML/Javascript work. And (being on a KDE desktop) I no longer have to put up with the memory hog that Eclipse really is. Quanta is more responsive and does just about everything that Eclipse did. I will definitely switch back to Eclipse when I get back into other languages (Java/C), as I really do like it, but just don't have the memory (512MB) or the money (0$) to get more. If you're doing work with PHP and are running KDE - you can run it elsewhere, but it will take more memory - you should consider taking a look at Quanta, which is probably already installed. Done with that, for now...&lt;br /&gt;&lt;br /&gt;So I downloaded the documentation for Paypal's API yesterday, hoping to easily get some good Paypal programming into my project. I need something very simple:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Person wants something, person selects it.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Person wants to pay for that thing, and clicks button to do so.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Person gets the options to pay via their paypal account, or through a credit card&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Information entered&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Information confirmed&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Confirmation Sent&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Simple enough, right? I took a look at the documentation, and was overwhelmed, for the first time in a while. There were thousands of pages of information, and sorting through it all was just not an option. For something as simple as the above, it shouldn't take a thousand pages. So I searched around the paypal developer's section. I found the paypal SDK (available for several different languages, my language this year is PHP), and I downloaded it. I imported it into my project manager, and voila, 5.8 Megs of a wonderfully organized PEAR installation. Oh. I haven't yet written about my thoughts of PEAR. I'll do that soon... But for the meantime, I just don't like it. If I'm going to be using code, I'd much rather it be available to me like my other code is, not through some installable module...&lt;br /&gt;&lt;br /&gt;So the PEAR stuff is disabled on my PHP installation, and I didn't feel like recompiling. So I continue my search, and enter the PayPal developer's forum. May I say how much useless, incomplete information lies within those walls? I did find a few posts that got me started, and finally realized that there was no way I would be getting through this without learning how to use SOAP. My first stop was the PHP manual, which told me that I needed to enable SOAP on my PHP install... I quickly opened up vi:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;  phpinfo();&lt;br /&gt;?&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Saved the file on my server, and opened it up.... &lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;'./configure' '--prefix=/usr/local/php' &lt;br&gt;'--with-apxs2=/usr/local/apache2/bin/apxs' '--with-libxml' &lt;br&gt;'--with-zlib' '--with-bz2' '--enable-calendar' '--with-jpeg-dir'&lt;br&gt; '--with-tiff-dir' '--with-gd' '--with-png-dir' '--with-zlib-dir' &lt;br&gt;'--with-freetype-dir=/usr/include/freetype2/' '--with-t1-lib' &lt;br&gt;'--with-mysql=/usr/local/mysql' '--with-mysql-sock=/tmp/mysql_sock/mysql.sock' &lt;br&gt;'--enable-sockets' '--with-tidy' '--with-gmp' '--with-openssl'&lt;br&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;DAMN! I need to recompile for that native PHP5 SOAP support, don't I!? ARGH!&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;  $ su -c removepkg PHP&lt;br /&gt;    password: X&lt;br /&gt;  $ cd /source/php5&lt;br /&gt;  $ make clean&lt;br /&gt;  $ ./configure --prefix=/package --EVERYTHING + --enable-soap&lt;br /&gt;  $ make&lt;br /&gt;  $ su -c make install&lt;br /&gt;  $ cd /package&lt;br /&gt;  $ su&lt;br /&gt;  # makepkg PHPwithSOAP.tgz &lt;br /&gt;  # installpkg PHPwithSOAP.tgz&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Okay. After restarting Apache, I had PHP with SOAP. I read the documentation at php.net more thoroughly, and got a pretty good idea of what I was doing. Now I may not yet be an expert with SOAP, but the following just seemed a little long:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt; $params = array(&lt;br /&gt; 'Version'=&gt;'1.0',&lt;br /&gt; 'DoExpressCheckoutPaymentRequestDetails'=&gt;array(&lt;br /&gt;  'Token'=&gt;$_GET['token'],&lt;br /&gt;  'PayerID'=&gt;$_GET['payerid'],&lt;br /&gt;  'PaymentAction'=&gt;'Sale',&lt;br /&gt;  'PaymentDetails'=&gt;array(&lt;br /&gt;    'OrderTotal'=&gt;$order_total,&lt;br /&gt;    'ItemTotal'=&gt;array('_'=&gt;'100.00', 'currencyID'=&gt;'USD'),&lt;br /&gt;    'TaxTotal'=&gt;array('_'=&gt;'0', 'currencyID'=&gt;'USD')&lt;br /&gt;    )&lt;br /&gt;  ),&lt;br /&gt; );&lt;br /&gt; &lt;br /&gt; $params = array('DoExpressCheckoutPaymentRequest'=&gt;$params);&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now why the heck would they make me waste the bandwidth and send them a string as long as "DoExpressCheckoutPaymentRequestDetails?" Can't they make that (and quite a few others) a little smaller? ARGH! Well, a few hours messing with my SOAP requests to Paypal, I finally got something working. I can now click a Pay now with Paypal button, and have a test account charge 100 dollars to a fake user. And the amount goes through! The only problem is the assloads of configuration I'm going to have to do to make this a good script that I can actually use for my sites! &lt;br /&gt;&lt;br /&gt;End Rant.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112740163637156077?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112740163637156077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112740163637156077' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112740163637156077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112740163637156077'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/09/programming-for-paypal.html' title='Programming for Paypal'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112703756311123309</id><published>2005-09-18T02:38:00.000-07:00</published><updated>2006-11-15T21:19:47.692-07:00</updated><title type='text'>Re-think your AJAX overuse</title><content type='html'>Okay. I know I've been posting loads of AJAX stuff recently, but after taking a look at how a few other sites are implementing this technology, I decided I need a warning: NOT ALL USERS BROWSE WITH JAVASCRIPT!&lt;br /&gt;&lt;br /&gt;AJAX programming is very well supported by the major browsers, but only if AJAX is enabled. Some stats point out that up to 30% of users browse the internet with javascript disabled. You need to be sure that you allow some method of viewing your page without javascript. So today, a quick discussion on the PHP DOM, which will probably throw out much of your JS DOM usage...&lt;br /&gt;&lt;br /&gt;The Javascript DOM makes it very easy to add information to each page after it is loaded, and this is exactly what most of the AJAX programs on the internet are doing these days (my div browser below is a good example of that). The best use of AJAX can also be the hardest to find a very quick substitute for. Take for instance the star feature on gmail. A click on the star sends a message through the request object to the gmail server, telling the server that the message should now be starred. No response is needed (although one may be given), and the client side script applies a star to the message. The best way to program something like this is definitely to program the non-AJAX version first, and then to add the new functionality for a browser that supports it.&lt;br /&gt;&lt;br /&gt;Anyway, the PHP DOM class: http://www.php.net/manual/en/ref.dom.php&lt;br /&gt;&lt;br /&gt;The basic usage is as follows:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;$dom = new DOMDocument;&lt;br /&gt;/* For HTML */&lt;br /&gt;$dom-&gt;loadHTML($html);&lt;br /&gt;/* For XML */&lt;br /&gt;$dom-&gt;loadXML($xml);&lt;br /&gt;$links = $dom-&gt;getElementsByTagName('a');&lt;br /&gt;foreach($links as $link){&lt;br /&gt;  /* Looping through each link in the provided HTML, get the location the link points to: */&lt;br /&gt;  $location = $link-&gt;getAttribute('href');&lt;br /&gt;  if($location == ''){&lt;br /&gt;       /* There was no href attribute, or it is empty. the DOM will not return false for this &lt;br /&gt;           method, if there was no location specified, send to the index (relative)*/&lt;br /&gt;      $link-&gt;setAttribute('href', 'index.php');&lt;br /&gt;  }else{&lt;br /&gt;       /* We are going to send the user through the safe_redirect script to avoid sharing&lt;br /&gt;          the session id */&lt;br /&gt;      $link-&gt;setAttribute('href', 'safe_out.php?loc='.$link);   &lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Read the documentation for this class, and you'll see it works in exactly the same way as the JS DOM. The example above changed all links on the page to move through the safe_out.php script, which could redirect a user to a page after stripping the phpsessid variable from the $_GET array, lessening the probablity for a Cross-site scripting attack...&lt;br /&gt;&lt;br /&gt;Again, I don't have much to write on today, as I haven't really had time to do anything interesting. No cool new features, just fixing bugs in code...&lt;br /&gt;&lt;br /&gt;Don't worry though, you non-existent audience (save you, of course &lt;a href="http://www.sitepoint.com/forums/showthread.php?t=300155"&gt;mav3n&lt;/a&gt;), I'll soon start putting up some more interesting stuff. &lt;br /&gt;&lt;br /&gt;-James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112703756311123309?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112703756311123309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112703756311123309' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112703756311123309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112703756311123309'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/09/re-think-your-ajax-overuse.html' title='Re-think your AJAX overuse'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112620201948714629</id><published>2005-09-08T10:31:00.000-07:00</published><updated>2006-11-15T21:19:47.618-07:00</updated><title type='text'>AJAX in-page browser pt 2</title><content type='html'>So. I've been working with my AJAX browser, and I've come across a problem. I set up user authentication with a script that is executed with every page that loads on the server... It checks to see whether or not the encrypted cookie or the session variables for log-in are accurate, and will forward to the log in page if they are not. I have an exception page array, which contains a list of pages that are allowed to be viewed by users who are not logged in. This makes things very secure.&lt;br /&gt;&lt;br /&gt;The AJAX browser I'm using in the form allows the user to browse through category information, specifying what category they would like to place their entry into. When the request is made to the script that loads the category information, the included file checks to see whether they are logged in or not and the log in page is displayed in the AJAX browser. The AJAX browser does not allow for the reading of the PHP session if it is in a cookie... &lt;br /&gt;&lt;br /&gt;If such a system is in place, the easiest solution is to force the PHP session id into the GET array passed to the div browser...&lt;br /&gt;&lt;br /&gt;Because of the authenticating include, you will also need to make sure that PHP sets the correct session id:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;if(isset($_GET['PHPSESSID'])){&lt;br /&gt;  session_id($_GET['PHPSESSID']);&lt;br /&gt;}&lt;br /&gt;session_start();&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Pretty easy... I guess you now know I couldn't think of anything to write today :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112620201948714629?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112620201948714629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112620201948714629' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112620201948714629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112620201948714629'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/09/ajax-in-page-browser-pt-2.html' title='AJAX in-page browser pt 2'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112604990784004391</id><published>2005-09-06T16:14:00.000-07:00</published><updated>2006-11-15T21:19:47.528-07:00</updated><title type='text'>AJAX in-page browser</title><content type='html'>Before you get into this post, if you don't know how to program with javascript and HTTPRequestObjects, you should look at my tutorial on PHPBuilder.com:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.phpbuilder.com/columns/kassemi20050606.php3"&gt;http://www.phpbuilder.com/columns/kassemi20050606.php3 (part 1)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.phpbuilder.com/columns/kassemi20050613.php3"&gt;http://www.phpbuilder.com/columns/kassemi20050613.php3 (part 2)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Yep. I wrote it. From what I gather, you either love it or hate it. It's been pretty popular (links to it show up when you google AJAX tutorial... :) )&lt;br /&gt;&lt;br /&gt;So I needed to allow a user to select from a number of options while in page form. There are many such options available... The closest example I can think about are school codes. For every school there is an assigned school code. To find the one that applies to you, you need to be able to search through a number of schools. This information is not easily accessible from a dropdown box. The solution? Have you seen those pages that have a calendar icon you can click on to get a calendar next to the form input (I have one of these on the page, as well)? Why not offer a way to let users browse information next to the form, much in the same way they can browse through the months in the calendars? An iframe would do the trick, but in order to keep away from frames entirely, we'll use a  div and some AJAX... Here's the PHP back-end to the whole thing. You can add security restrictions, as I have done:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;span style="color: #000000"&gt;&lt;br /&gt;&lt;span style="color: #0000BB"&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;/* PHP backend for AJAX browser */&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;file_get_contents&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$_GET&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'to'&lt;/span&gt;&lt;span style="color: #007700"&gt;]);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;stripos&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'&amp;lt;body'&lt;/span&gt;&lt;span style="color: #007700"&gt;) !== &lt;/span&gt;&lt;span style="color: #0000BB"&gt;true&lt;/span&gt;&lt;span style="color: #007700"&gt;){&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$start &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;stripos&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'&amp;lt;body'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$end &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;stripos&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'&amp;gt;'&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$start&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;substr&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$end &lt;/span&gt;&lt;span style="color: #007700"&gt;+ &lt;/span&gt;&lt;span style="color: #0000BB"&gt;1&lt;/span&gt;&lt;span style="color: #007700"&gt;); &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;stripos&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'&amp;lt;/body&amp;gt;'&lt;/span&gt;&lt;span style="color: #007700"&gt;) !== &lt;/span&gt;&lt;span style="color: #0000BB"&gt;false&lt;/span&gt;&lt;span style="color: #007700"&gt;){&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;substr&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;stripos&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'&amp;lt;/body&amp;gt;'&lt;/span&gt;&lt;span style="color: #007700"&gt;));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$_GET&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'div_id'&lt;/span&gt;&lt;span style="color: #007700"&gt;].&lt;/span&gt;&lt;span style="color: #DD0000"&gt;','&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;All it does is return the data from a page (anything within the body element, if it exists), and the id that we pass to it... Here's the js... Everything is extremely simple:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;/* (Copyright 2005 James Kassemi) */&lt;br /&gt; &lt;br /&gt;function getHTTPObject() { &lt;br /&gt; var xmlhttp; &lt;br /&gt; /*@cc_on &lt;br /&gt; @if (@_jscript_version &amp;gt;= 5) &lt;br /&gt;  try { &lt;br /&gt;   xmlhttp = new ActiveXObject(&amp;quot;Msxml2.XMLHTTP&amp;quot;); &lt;br /&gt;  } catch (e) { &lt;br /&gt;   try { xmlhttp = new ActiveXObject(&amp;quot;Microsoft.XMLHTTP&amp;quot;); &lt;br /&gt;   } catch (E) { &lt;br /&gt;    xmlhttp = false; &lt;br /&gt;   } &lt;br /&gt;  } &lt;br /&gt;  &lt;br /&gt; @else &lt;br /&gt;  xmlhttp = false; &lt;br /&gt; @end @*/  &lt;br /&gt; if (!xmlhttp &amp;amp;&amp;amp; typeof XMLHttpRequest != 'undefined') { &lt;br /&gt;  try { &lt;br /&gt;   xmlhttp = new XMLHttpRequest(); &lt;br /&gt;  } catch (e) { &lt;br /&gt;   xmlhttp = false; &lt;br /&gt;  } &lt;br /&gt; } &lt;br /&gt; return xmlhttp; &lt;br /&gt;} &lt;br /&gt;var http = getHTTPObject(); &lt;br /&gt;&lt;br /&gt;function request_o(http_object, method, url, capture_function, post_args){&lt;br /&gt;  http_object.abort();&lt;br /&gt;  http_object.open(method, url);&lt;br /&gt;  if(method=='post'){&lt;br /&gt;   http_object.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');&lt;br /&gt;   http_object.onreadystatechange = eval(capture_function);&lt;br /&gt;   http_object.send(post_args);&lt;br /&gt;  }&lt;br /&gt;  if(method != 'post'){&lt;br /&gt;   http_object.onreadystatechange = eval(capture_function);&lt;br /&gt;   http_object.send(null);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function navigate(to, div_id){&lt;br /&gt; request_o(http, 'GET', './div_browser.php?to=' + escape(to) + '&amp;amp;div_id=' + escape(div_id), 'handle_navigate'); &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;function handle_navigate(){&lt;br /&gt; if(http.readyState == 4){&lt;br /&gt;  /* This could be done using XML and certain procedures I've used before, but in this case this will work just fine... */&lt;br /&gt;  var response = http.responseText;&lt;br /&gt;  /* Instead of using split, we'll use our own procedure that should be a little faster. */&lt;br /&gt;  for(i=0;i&amp;lt;response.length;i++){&lt;br /&gt;   if(response.charAt(i) == ','){&lt;br /&gt;    var div_id = response.substring(0,i);&lt;br /&gt;    var content = response.substring(i+1);&lt;br /&gt;    break;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  /* We now have the content for the div, and we have the div's id... Let's replace with content. */&lt;br /&gt;  document.getElementById(div_id).innerHTML = content;&lt;br /&gt;  /* Now we should convert the links inside to open in the same box... */&lt;br /&gt;  convert_links(div_id);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function convert_links(div){&lt;br /&gt; /* Convert all anchor links to navigate() links... */&lt;br /&gt; div_box = document.getElementById(div);&lt;br /&gt; var links = div_box.getElementsByTagName('a');&lt;br /&gt;  for(i=0;i&amp;lt;links.length;i++){&lt;br /&gt;   var value = links.item(i).getAttribute('href');&lt;br /&gt;  if(value){&lt;br /&gt;   links.item(i).setAttribute('href', &amp;quot;javascript:navigate('&amp;quot; + escape(value) + &amp;quot;', '&amp;quot; + div + &amp;quot;');&amp;quot;);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And that's pretty much the entire thing! A call to navigate(to, div_id) will replace the contents of div_id with the page, to. I added a few more options more specific to my site (including a little icon that can be clicked next to the form field, as I was talking about), and grabbed the obligatory slashdot.org screenshot:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/ajaxbrowser.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/ajaxbrowser.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;  &lt;br /&gt;I'm not saying this is a full solution for anything, but it could easily become one. You could add your own back, forward, and home buttons, and could even insert a navigation bar, where the person can enter whatever URL they want to have loaded. &lt;br /&gt;&lt;br /&gt;One thing that would need some serious work, however, would be the convert_links function. It currently just takes anything that is in the href attribute of a link and adds the navigate event to it, so it will load in the current div... The problem with this is that it will not render relative links in functional format... &lt;br /&gt;&lt;br /&gt;If you are going to expand this, be sure you're careful about security. Make certain no administrator-like page on your server or anything checks authenticity only by whether or not you're on localhost... There are quite a few things somebody could easily do with this technology if they wanted to. You may wish to consider adding a check that only loads pages that are on your own server, and further, only pages that you want accessed...&lt;br /&gt;&lt;br /&gt;Until next time,&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112604990784004391?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112604990784004391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112604990784004391' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112604990784004391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112604990784004391'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/09/ajax-in-page-browser.html' title='AJAX in-page browser'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112576624679291641</id><published>2005-09-03T09:41:00.000-07:00</published><updated>2006-11-15T21:19:47.439-07:00</updated><title type='text'>Keeping my laptop cool</title><content type='html'>Last night as I was going to bed, I stared at the ceiling and wondered how I would keep my laptop free of dust. I've got an hp pavilion ze4420us (slackware-current and FULLY functional (including 3d acceleration, YAY), and I live in a very dirty room - as most males my age do. Since there's quite a bit of dust in here, the fan on this thing gets clogged regularly. About every day I squirt some compressed air into the fan intake, and every month I open the thing up completely to clean it out. Since I have no money - as most males my age don't - I decided I need something more affordable than compressed air. My roommate thinks it's necessary to do laundry every week (don't worry, I still smell fine), and she's got loads of dryer sheets. I wasn't too sure whether or not that would work, so today I started browsing the internet, and came across this:&lt;br /&gt;&lt;br /&gt;http://www.afrotechmods.com/reallycheap/freshener/freshener.htm&lt;br /&gt;&lt;br /&gt;What'd'ya know!? So I cut up a dryer sheet, and put it over the intake fan... My idle CPU temp jumped from 50 to 58 degrees, but if I don't have to worry about the dust, that's just fine. I'll take a look at the sheet in a week and see just what it catches. If it's got something interesting I'll find a way to get a photo of it up here (btw: will take your old digital camera :) ).&lt;br /&gt;&lt;br /&gt;As for the AJAX syntax highlighter... Someone on sitepoint the other day was looking for some help making a guestbook for his daughter's web page, so I decided I'd help out and write one for him. It's pretty advanced, and I'll get you more information about that one when I'm done with it.&lt;br /&gt;&lt;br /&gt;I'm also thinking of moving this blog. I don't like the way that blogger is set up. I can't upload files easily, categorize entries, etc. So once I find something better I'll try to export this to it. &lt;br /&gt;&lt;br /&gt;Take it easy everybody!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112576624679291641?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112576624679291641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112576624679291641' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112576624679291641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112576624679291641'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/09/keeping-my-laptop-cool.html' title='Keeping my laptop cool'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112544230577386240</id><published>2005-08-30T15:51:00.000-07:00</published><updated>2006-11-15T21:19:47.361-07:00</updated><title type='text'></title><content type='html'>&lt;h2&gt;The AJAX Syntax Highlighter ... Coming soon!&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Note: Still looking for file hosting. All open source stuff, just many different projects / advice pieces in one place. Anybody who's interested, please e-mail me (jkassemi at gmail dot com). Thanks.&lt;br /&gt;&lt;br /&gt;Remember when I said I was going to work on that syntax highlighter with AJAX and the DOM? Well, I found the tool I'm going to use... http://colorer.sourceforge.net/ &lt;br /&gt;&lt;br /&gt;It offers loads of syntax highlighters, and it will be VERY easy to get this project done with it. The question is now whether I work directly off of the API and create code that everybody on all systems can use it with ( I have no life option ), or just use shell_exec ( I have no life option ( DAMN ) ) to read the output of the syntax... &lt;br /&gt;&lt;br /&gt;Well, only time will tell, as today I only have a very limited of time to do anything but work. I'm right in the middle of some more optimizations and bug fixes for my main project. I'll probably have the code up tomorrow. &lt;br /&gt;&lt;br /&gt;Until next time!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112544230577386240?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112544230577386240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112544230577386240' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112544230577386240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112544230577386240'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/08/remember-when-i-said-i-was-going-to.html' title=''/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112533773063704751</id><published>2005-08-29T10:09:00.000-07:00</published><updated>2006-11-15T21:19:47.285-07:00</updated><title type='text'>ARGH! (Learn good programming practice early part two)</title><content type='html'>First, let me inform everybody that I'm looking for a place to host files for this blog. It's difficult to take code that's posted all over a page, and blogger doesn't help much, as they take out some of the markup, so I'm never sure if the code I &lt;i&gt;do&lt;/i&gt; post actually works when you copy and paste it. The solution is just to give everybody a tar.gz'd or tar.bz2'd file... I'm also going to start working on an AJAX syntax highlighter for the code here, that would search through the page for code elements and highlight them appropriately. I already have such a system for help information on my current project, so changing that wouldn't be that hard. The only problem is I need a place to put a javascript and php file, so I can include that functionality here.&lt;br /&gt;&lt;br /&gt;Now to the ARGH! portion... When I first started programming in PHP (about a year or so), I took a look at a sessions tutorial so I could create a login page for my first project, a forum that allowed infinite category creation and customization... Pretty nice, but looking at it after I had done some work, I realized that it would never be commercially suitable. The tutorial, which I wish I could find, said that all I needed to do to provide a login for the user was something like this (I use my mysql class for this stuff, but you can figure it out):&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;  session_start();&lt;br /&gt;  $db-&gt;query(sprintf("select password from users where username='%s'",&lt;br /&gt;     mysql_real_escape_string($_POST['username'])));&lt;br /&gt;  if($db-&gt;result() == $_POST['password']){ &lt;br /&gt;     $_SESSION['username'] = $_POST['username'];&lt;br /&gt;  }else{&lt;br /&gt;     echo "ERROR!";&lt;br /&gt;  }&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;That was great. All I needed to do was present the user a form with a password and username, attach something like the above to it, and:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;   /* WARNING: THIS IS &lt;i&gt;NOT&lt;/i&gt; GOOD. DON'T DO. JUST DEMONSTRATING SOMETHING */&lt;br /&gt;   session_start();&lt;br /&gt;   if(isset($_SESSION['username'])){&lt;br /&gt;      echo "I'm a valid log-in!";&lt;br /&gt;   }&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Because sessions are the most secure fucking things on the planet, right? ARGH!&lt;br /&gt;&lt;br /&gt;So I started programming that way for a while, until everything I'd done used that technique to get what user was logged in, whether the user was logged in, and whether the user's login was valid... Soon enough my code base was polluted, and I decided I'd fix it later, putting the date off forever. Sure enough, the day I had to fix it was today! I decided I didn't want to mess around with SSL for this site, which doesn't really have information that needs that much protection, but I didn't want any packet spy to get the passwords for my users when they loaded the page up on a public network. So I decided to go with a javascript md5 hash solution...&lt;br /&gt;&lt;br /&gt;I create a database:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;challenge | ip | created&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Which holds a randomly created variable, the challenge, the ip that requested the challenge, and the time in which the challenge was created... I actually used an additional column, `type', as I want to have those image challenges sent too (remember yesterday's cool spirals?). &lt;br /&gt;&lt;br /&gt;So, whenever a user wants to log in, they are given a form that has the following inputs:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Username [GET:username];&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Password [We'll get to this];&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Image challenger [GET:image_challenge];&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;A challenge is randomly created using this code:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;function genRandStr($length){&lt;br /&gt;    $st=array(48,65,97);&lt;br /&gt;    $en=array(57,90,122);    &lt;br /&gt;    $chr="";&lt;br /&gt;    for($i=0;$i&lt;$length;$i++){&lt;br /&gt;    $rnd=rand(0,2);&lt;br /&gt;        $chr.=chr(rand($st[$rnd],$en[$rnd]));&lt;br /&gt;    }&lt;br /&gt;    return $chr;&lt;br /&gt;} &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This is sent to a hidden field on the form, "challenge."&lt;br /&gt;&lt;br /&gt;When the user fills out the username, password, and characters in the image, the following is executed:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt; var challenge = document.getElementById('challenge').value;&lt;br /&gt; var username = document.getElementById('username').value;&lt;br /&gt; var password = document.getElementById('password').value;&lt;br /&gt; var challenge_image = document.getElementById('challenge_image').value;&lt;br /&gt; var final_hash = hex_md5(password);&lt;br /&gt; final_hash = hex_md5(final_hash+challenge+username);&lt;br /&gt; location.href = "login.php?username=" + username + "&amp;challenge_image=" + challenge_image + "&amp;secured_pass=" + final_hash + "&amp;challenge=" + challenge;&lt;br /&gt; &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The md5 library for javascript that I use can be found here:&lt;br /&gt;&lt;a href="http://pajhome.org.uk/crypt/md5/index.html"&gt;http://pajhome.org.uk/crypt/md5/index.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Basically, I convert all the password, along with the challenge, to an md5 hash... Which gets sent over the network to my login script again. This means that the password itself is not sent, meaning a packet sniffer can't get a hold of them. The packet sniffer does see the challenge string, though, but it still can't do anything with it... Brute forcing that combination would take some time...&lt;br /&gt;&lt;br /&gt;login.php takes a look to see if all of the information is in order, and then does the following:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;/* The type is because this is the challenge image string... 1=challenge image, 0=login challenge */&lt;br /&gt;$connection-&gt;query(sprintf("select * from security_challenges where ip='%s' and type=1 and challenge='%s'",&lt;br /&gt;  mysql_real_escape_string($_SERVER['REMOTE_ADDR']),&lt;br /&gt;  mysql_real_escape_string($_GET['challenge_image'])));&lt;br /&gt;if($connection-&gt;numrows() == 0){ /* They didn't type the challenge image string in right */}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;$connection-&gt;query(sprintf("select challenge from security_challenges where ip='%s' and type=0 and challenge='%s'",&lt;br /&gt;   mysql_real_escape_string($_SERVER['REMOTE_ADDR']),&lt;br /&gt;   mysql_real_escape_string($_GET['challenge'])));&lt;br /&gt;$challenge_db = $connection-&gt;result();&lt;br /&gt;&lt;br /&gt;if($connection-&gt;numrows() == 0){ /* We couldn't find the challenge that they said they used */}&lt;br /&gt;&lt;br /&gt;/* Get the password, we're doing this the same way I did before */&lt;br /&gt;$connection-&gt;query(sprintf("select password from br_registered where username='%s'",&lt;br /&gt;       mysql_real_escape_string($_GET['username'])));&lt;br /&gt;&lt;br /&gt;if($connection-&gt;numrows() &lt;&gt; 1){ /* The username wasn't found */}&lt;br /&gt;$password_db = $connection-&gt;result();&lt;br /&gt;$hash_compare = md5($password_db.$challenge_db.$_GET['username']);&lt;br /&gt;&lt;br /&gt;if($hash_compare &lt;&gt; $_GET['secured_pass']){&lt;br /&gt;  /* The hash we created with the javacript and the hash we just used to check the js hash didn't&lt;br /&gt;   * match. Do not allow the user access with whatever routine you put in here. */&lt;br /&gt;}else{&lt;br /&gt;  /* The hashes DID match */&lt;br /&gt;        /* This is a little more secure. We're not holding the password in the session,&lt;br /&gt;         * but another hash. $secure_global_pass is a secret phrase that should get changed&lt;br /&gt;         * every two weeks or so. */&lt;br /&gt; $password_secure_compare = md5(md5($password_db).$secure_global_pass.$username);&lt;br /&gt;        $_SESSION['username'] = strtolower($_GET['username']);&lt;br /&gt; $_SESSION['password_secure'] = $password_secure_compare;&lt;br /&gt;   /* Do what you will to give the user access. Forward to another page, whatever.... */&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Great. So we're able to get a user logged in securely. The image bit might be a little excessive, but I like it, so I'm going to use it. If I get a single complaint from a user, it'll come right down... But how am I now getting the username and checking that the username is valid? I include this file with everything I do that requires a login... "logincheck.php":&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;function username(){ /* Return the username of the logged in user. */&lt;br /&gt; global $secure_global_pass;&lt;br /&gt;        /* Get the login information, if it's stored in a cookie or in an active session */&lt;br /&gt; if(isset($_COOKIE['your_site'])){&lt;br /&gt;  @$username = $_COOKIE['your_site']['username'];&lt;br /&gt;  @$password_secure = $_COOKIE['your_site']['password_secure'];&lt;br /&gt; }elseif(isset($_SESSION['username'])){&lt;br /&gt;  @$username = $_SESSION['username'];&lt;br /&gt;  @$password_secure = $_SESSION['password_secure']; &lt;br /&gt; }else{ &lt;br /&gt;  return false;&lt;br /&gt; }&lt;br /&gt; include_once('./class/mysql.php');&lt;br /&gt; $db = new mysqlConnection();&lt;br /&gt; $db-&gt;change('whatever_database_you_use');&lt;br /&gt; $db-&gt;query(sprintf("select password from users where username='%s'",&lt;br /&gt;  mysql_real_escape_string($username)));&lt;br /&gt; if($db-&gt;numrows == 0){&lt;br /&gt;  return false; &lt;br /&gt; }&lt;br /&gt; $password_database = $db-&gt;result(); &lt;br /&gt; $password_secure_compare = md5(md5($password_database).$secure_global_pass.$username);&lt;br /&gt; /* We're comparing another generated hash with the one supplied to us. If they&lt;br /&gt;         * don't match, the user is spoofing something, and shouldn't be allowed to see &lt;br /&gt;         * this page */&lt;br /&gt;        if($password_secure_compare &lt;&gt; $password_secure){&lt;br /&gt;  return false;&lt;br /&gt; }else{&lt;br /&gt;        /* Since somebody might be viewing this page after saving the information to a cookie,&lt;br /&gt;         * we should log them in. */&lt;br /&gt;  /* Place the log-in in the session. */&lt;br /&gt;  $_SESSION['username'] = $username;&lt;br /&gt;  $_SESSION['pass_secure'] = $password_secure;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return $_SESSION['username']; &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* And here's the routine that's called on every page: */&lt;br /&gt;$current_user = username();&lt;br /&gt;if($current_user === false){&lt;br /&gt;     /* However you prefer to do this is fine */&lt;br /&gt;     page_forward('./login.php');&lt;br /&gt;     exit;&lt;br /&gt;} &lt;br /&gt;&lt;/div&gt; &lt;br /&gt;&lt;br /&gt;So, if the user isn't logged in correctly, they are forwarded immediately to the login page... Now, to get rid of the old method took replacing over 2000 references to $_SESSION['username'] for a username with $current_user. Since some of the $_SESSION['username'] instances were actually needed to modify the session, I had check each instance before I replaced it. Too much work.&lt;br /&gt;&lt;br /&gt;Hope you get some ideas from that!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112533773063704751?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112533773063704751/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112533773063704751' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112533773063704751'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112533773063704751'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/08/argh-learn-good-programming-practice.html' title='ARGH! (Learn good programming practice early part two)'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112525852134308981</id><published>2005-08-28T12:32:00.000-07:00</published><updated>2006-11-15T21:19:47.189-07:00</updated><title type='text'>Proving human existence: user authentication images</title><content type='html'>You've seen them everywhere (and probably have already programmed yours, so this is useless, but if not), and you know they're effective at keeping scripts from posting comments (at least) to your site. They are simple images that contain a string of numbers and letters, that the user needs to type into an input box to prove they're not a shell script. We'll use my image class that I posted yesterday to start this out. Don't make fun of my image class for missing certain obvious things that I realized where missing today. I didn't fix the image class yet, but I might if I ever get an audience and that audience wants a good one. Here is the class that extends the image class for creating those functions:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Basic PHP Image class&lt;br /&gt;* Copyright (C) 2005 James Kassemi&lt;br /&gt;*&lt;br /&gt;* This library is free software; you can redistribute it and/or&lt;br /&gt;* modify it under the terms of the GNU Lesser General Public&lt;br /&gt;* License as published by the Free Software Foundation; either&lt;br /&gt;* version 2.1 of the License, or (at your option) any later version.&lt;br /&gt;&lt;br /&gt;* This library is distributed in the hope that it will be useful,&lt;br /&gt;* but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU&lt;br /&gt;* Lesser General Public License for more details.&lt;br /&gt;&lt;br /&gt;* You can view the LGPL here: http://www.gnu.org/licenses/lgpl.html */&lt;br /&gt;class image_manipulation extends image {&lt;br /&gt; public $image;&lt;br /&gt; public $width;&lt;br /&gt; public $height;&lt;br /&gt; public $color;&lt;br /&gt; &lt;br /&gt; function new_image($width=200, $height=200){&lt;br /&gt;  $this-&gt;width = $width;&lt;br /&gt;  $this-&gt;height = $height;&lt;br /&gt;  $this-&gt;image = imagecreatetruecolor($width, $height);&lt;br /&gt;  imageantialias($this-&gt;image, true);&lt;br /&gt;  $background = imagecolorallocate($this-&gt;image, 225, 228, 169);&lt;br /&gt;  imagefill($this-&gt;image, 0, 0, $background);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; function get_color($red, $green, $blue){&lt;br /&gt;  return imagecolorallocate($this-&gt;image, $red, $green, $blue); &lt;br /&gt; } &lt;br /&gt; &lt;br /&gt; function create_swirl_template($x, $y, $color, $angle_step=.05, $start_size=5, $size_stepx=.5, $size_stepy=.5, $revolutions=5, $rand_step_var=0){&lt;br /&gt;  $x = rand(0, $this-&gt;width);&lt;br /&gt;  $y = rand(0, $this-&gt;height);&lt;br /&gt;  &lt;br /&gt;  $angle = rand(0, 360);&lt;br /&gt;  $sizex = $start_size;&lt;br /&gt;  $sizey = $start_size;&lt;br /&gt;&lt;br /&gt;  $steps_total = (360/$angle_step) * $revolutions;&lt;br /&gt;  for($i=0;$i&lt;$steps_total;$i++){&lt;br /&gt;   if($rand_step_var &gt; 0){&lt;br /&gt;    $size_0x = rand(-$rand_step_var, $rand_step_var) + $sizex;&lt;br /&gt;    $size_0y = rand(-$rand_step_var, $rand_step_var) + $sizey; &lt;br /&gt;   }else{&lt;br /&gt;    $size_0x = $sizex;&lt;br /&gt;    $size_0y = $sizey;&lt;br /&gt;   }&lt;br /&gt;   $y_0 = $size_0y * sin($angle);&lt;br /&gt;   $x_0 = $size_0x * cos($angle);&lt;br /&gt;   /* Optimizations */&lt;br /&gt;    while((&lt;br /&gt;       (($x_0 + $x) &gt; $this-&gt;width || ($y_0 + $y) &gt; $this-&gt;height) ||&lt;br /&gt;       (($x_0 + $x) &lt; 0 || ($y_0 + $y) &lt; 0)&lt;br /&gt;      )&lt;br /&gt;       &amp;&amp; $i &lt; $steps_total){&lt;br /&gt;     $angle = $angle + $angle_step;&lt;br /&gt;     $sizex = $sizex + $size_stepx;&lt;br /&gt;     $sizey = $sizey + $size_stepy;&lt;br /&gt;     $x_0 = $size_0x * cos($angle);&lt;br /&gt;     $y_0 = $size_0y * sin($angle); &lt;br /&gt;     $i++;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   /* END Optimizations */&lt;br /&gt;   $color_s = $color[rand(0,count($color)-1)];&lt;br /&gt;   //imagesetpixel($this-&gt;image, $x + $x_0, $y + $y_0, $color_s);&lt;br /&gt;   imagefilledellipse($this-&gt;image, $x + $x_0, $y+$y_0, 2, 2, $color_s);&lt;br /&gt;   $angle = $angle + $angle_step;&lt;br /&gt;   $sizex = $sizex + $size_stepx;&lt;br /&gt;   $sizey = $sizey + $size_stepy;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt; function string_it($string, $color){&lt;br /&gt;  $temp_string_placement = imagecreatetruecolor($this-&gt;width, $this-&gt;height);&lt;br /&gt;  imageantialias($temp_string_placement, true);&lt;br /&gt;  $background = imagecolorallocate($temp_string_placement, 125, 125, 125);&lt;br /&gt;  imagefill($temp_string_placement, 0, 0, $background);&lt;br /&gt;  $black = imagecolorallocate($temp_string_placement, 0, 0, 0);&lt;br /&gt;  $red = imagecolorallocate($temp_string_placement, 255, 255, 255);&lt;br /&gt;  $font = imagepsloadfont('./font.pfb');&lt;br /&gt;  $box_width = ($this-&gt;width / strlen($string))-10;&lt;br /&gt;  for($i=0;$i&lt;strlen($string);$i++){&lt;br /&gt;   $x = $box_width * $i + 20;&lt;br /&gt;   $y = rand(40, $this-&gt;height);&lt;br /&gt;   if($i%2 == 0){&lt;br /&gt;    imagepstext($temp_string_placement, substr($string, $i, 1), $font, 40, $black, $background, $x, $y);    &lt;br /&gt;   }else{&lt;br /&gt;    imagepstext($temp_string_placement, substr($string, $i, 1), $font, 40, $red, $background, $x, $y);     &lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  for($i=0;$i&lt;$this-&gt;width;$i++){&lt;br /&gt;   for($i2=0;$i2&lt;$this-&gt;height;$i2++){&lt;br /&gt;    $rgb = ImageColorAt($temp_string_placement, $i, $i2);&lt;br /&gt;&lt;br /&gt;    if($rgb == 0){&lt;br /&gt;     $color_s = $color[rand(0,2)];&lt;br /&gt;     imagefilledellipse($this-&gt;image, $i, $i2, 3, 3, $color_s);&lt;br /&gt;    }elseif($rgb==16777215){&lt;br /&gt;     $color_s = $color[rand(3,5)]; &lt;br /&gt;     imagefilledellipse($this-&gt;image, $i, $i2, 3, 3, $color_s);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   } &lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; function print_display(){&lt;br /&gt;  $this-&gt;output($this-&gt;image, 'jpg', 100);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Okay. This one is pretty cool, really... I started out with grand intentions, but ended up with something that works just as well, and is a little quicker. What I was trying to do was create a spiral blur over text that was placed on an image. This would make it difficult for text recognition software to figure out what the text was... I would randomly create a spiral for every different blur, so they couldn't plot it out.&lt;br /&gt;&lt;br /&gt;What I did instead was just use the spiral art, as it works without needing to add the additional blur layer... Just for kicks before I get started, with a few small changes to the spiral code, I generated these...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/image11.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/image11.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;create_swirl_template(200,40,$colors, 0.01, 0.5, 0.2, 0.1, 3, 6);&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/image2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/image2.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;create_swirl_template(250,250,$colors, 0.2, 0.5, 0.05, 0.04, 6, 5);&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/image3.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/image3.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;create_swirl_template(250,250,$colors, 0.002, 0.5, 0.05, 0.04, 6, 5);&lt;br /&gt;&lt;br /&gt;Okay. I'm done showing off today's fun side of the work... We actually had something to do, right? Notice the commented imagepixelset() line? It was changed to imagefilledelipse() to make the shapes a little more clear... The following can be used to produce verification images:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;$image = new image_manipulation;&lt;br /&gt;$image-&gt;new_image(250,100);&lt;br /&gt;$colors = array($image-&gt;get_color(24, 64, 130),&lt;br /&gt;    $image-&gt;get_color(0, 0, 20),&lt;br /&gt;    $image-&gt;get_color(0 ,0 ,10));&lt;br /&gt;$image-&gt;create_swirl_template(200,40,$colors, 0.03, 0.5, 0.2, 0.1, 3,2);&lt;br /&gt;$colors = array($image-&gt;get_color(50, 50, 0),&lt;br /&gt;    $image-&gt;get_color(50, 50, 50),&lt;br /&gt;    $image-&gt;get_color(100 ,100 ,100));&lt;br /&gt;$image-&gt;create_swirl_template(5,75,$colors, 0.04, 0.5, 0.2, 0.1, 3,2);&lt;br /&gt;$colors = array($image-&gt;get_color(0, 64, 130),&lt;br /&gt;    $image-&gt;get_color(0, 0,0),&lt;br /&gt;    $image-&gt;get_color(0 ,0 ,255),&lt;br /&gt;    $image-&gt;get_color(50, 50, 50),&lt;br /&gt;    $image-&gt;get_color(0, 0,0),&lt;br /&gt;    $image-&gt;get_color(0 ,0 ,255) );&lt;br /&gt;$image-&gt;string_it("R5f2g", $colors);&lt;br /&gt;$image-&gt;print_display();&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;That look exactly like this (changes spiral position, character position randomly when live):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/verify.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/verify.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Or you can obviously change colors, and layer things differently. Here's an example where the text is positioned below the spirals, and the text color matches the spirals:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;$image = new image_manipulation;&lt;br /&gt;$image-&gt;new_image(250,100);&lt;br /&gt;$colors = array($image-&gt;get_color(50, 50, 0),&lt;br /&gt;    $image-&gt;get_color(50, 50, 50),&lt;br /&gt;    $image-&gt;get_color(100 ,100 ,100),&lt;br /&gt;    $image-&gt;get_color(24, 64, 130),&lt;br /&gt;    $image-&gt;get_color(0, 0, 20),&lt;br /&gt;    $image-&gt;get_color(0 ,0 ,10) );&lt;br /&gt;$image-&gt;string_it("R5f2g", $colors);&lt;br /&gt;$colors = array($image-&gt;get_color(24, 64, 130),&lt;br /&gt;    $image-&gt;get_color(0, 0, 20),&lt;br /&gt;    $image-&gt;get_color(0 ,0 ,10));&lt;br /&gt;$image-&gt;create_swirl_template(200,40,$colors, 0.03, 0.5, 0.2, 0.1, 3,2);&lt;br /&gt;$colors = array($image-&gt;get_color(50, 50, 0),&lt;br /&gt;    $image-&gt;get_color(50, 50, 50),&lt;br /&gt;    $image-&gt;get_color(100 ,100 ,100));&lt;br /&gt;$image-&gt;create_swirl_template(5,75,$colors, 0.04, 0.5, 0.2, 0.1, 3,2);&lt;br /&gt;&lt;br /&gt;$image-&gt;print_display();&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/verify2.jpg"&gt;&lt;img style="text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/verify2.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;With a quick little hack we can make it even more difficult to isolate the text from the background:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt; function create_swirl_template($x, $y, $color, $angle_step=.05, $start_size=5, $size_stepx=.5, $size_stepy=.5, $revolutions=5, $rand_step_var=0, $line=false){&lt;br /&gt;  $x = rand(0, $this-&gt;width);&lt;br /&gt;  $y = rand(0, $this-&gt;height);&lt;br /&gt;  &lt;b&gt;$x_old = 0;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;$y_old = 0;&lt;/b&gt;&lt;br /&gt;  &lt;br /&gt;  $angle = rand(0, 360);&lt;br /&gt;  $sizex = $start_size;&lt;br /&gt;  $sizey = $start_size;&lt;br /&gt;&lt;br /&gt;  $steps_total = (360/$angle_step) * $revolutions;&lt;br /&gt;  for($i=0;$i&lt;$steps_total;$i++){&lt;br /&gt;   if($rand_step_var &gt; 0){&lt;br /&gt;    $size_0x = rand(-$rand_step_var, $rand_step_var) + $sizex;&lt;br /&gt;    $size_0y = rand(-$rand_step_var, $rand_step_var) + $sizey; &lt;br /&gt;   }else{&lt;br /&gt;    $size_0x = $sizex;&lt;br /&gt;    $size_0y = $sizey;&lt;br /&gt;   }&lt;br /&gt;   $y_0 = $size_0y * sin($angle);&lt;br /&gt;   $x_0 = $size_0x * cos($angle);&lt;br /&gt;   /* Optimizations */&lt;br /&gt;    while((&lt;br /&gt;       (($x_0 + $x) &gt; $this-&gt;width || ($y_0 + $y) &gt; $this-&gt;height) ||&lt;br /&gt;       (($x_0 + $x) &lt; 0 || ($y_0 + $y) &lt; 0)&lt;br /&gt;      )&lt;br /&gt;       &amp;&amp; $i &lt; $steps_total){&lt;br /&gt;     $angle = $angle + $angle_step;&lt;br /&gt;     $sizex = $sizex + $size_stepx;&lt;br /&gt;     $sizey = $sizey + $size_stepy;&lt;br /&gt;     $x_0 = $size_0x * cos($angle);&lt;br /&gt;     $y_0 = $size_0y * sin($angle); &lt;br /&gt;     &lt;b&gt;$x_old = $x_0;&lt;/b&gt;&lt;br /&gt;     &lt;b&gt;$y_old = $y_0;&lt;/b&gt;&lt;br /&gt;     $i++;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   /* END Optimizations */&lt;br /&gt;   $color_s = $color[rand(0,count($color)-1)];&lt;br /&gt;   //imagesetpixel($this-&gt;image, $x + $x_0, $y + $y_0, $color_s);&lt;br /&gt;   &lt;b&gt;if(!$line){&lt;/b&gt;&lt;br /&gt;    imagefilledellipse($this-&gt;image, $x + $x_0, $y+$y_0, 2, 2, $color_s);&lt;br /&gt;   &lt;b&gt;}else{&lt;br /&gt;    imageline($this-&gt;image, ($x + $x_0), ($y + $y_0), ($x + $x_old), ($y + $y_old), $color_s);&lt;br /&gt;    imageline($this-&gt;image, ($x + $x_0 + 1), ($y + $y_0 + 1), ($x + $x_old + 1), ($y + $y_old + 1), $color_s);&lt;br /&gt;    imageline($this-&gt;image, ($x + $x_0 - 1), ($y + $y_0 - 1), ($x + $x_old - 1), ($y + $y_old - 1), $color_s);&lt;br /&gt;   }&lt;/b&gt;&lt;br /&gt;   $angle = $angle + $angle_step;&lt;br /&gt;   $sizex = $sizex + $size_stepx;&lt;br /&gt;   $sizey = $sizey + $size_stepy;&lt;br /&gt;   &lt;b&gt;$x_old = $x_0;&lt;/b&gt;&lt;br /&gt;   &lt;b&gt;$y_old = $y_0;&lt;/b&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Which turns out something like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6529/1119/1600/verify3.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6529/1119/320/verify3.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The color array can be programmed for any RGB color values. As characters are printed, they alternate between using indexes 0-2 and indexes 3-5 on the color array for the string_it function. There is also an extra spiral on this image, but it is not truly necessary. Performance isn't bad. I have been getting an average of a single second rendering on my test server, which is quite good for a PHP program... If the calculations were to be done in C/C++, and then the result imported into PHP it might be a bit faster, but that's outside the scope of my discussion. &lt;br /&gt;&lt;br /&gt;By using the interlapping lines and different colors, it is very difficult to get a good selection of the text by changing anything in your image editing software, which also indicates it will be very hard for a script to do it. I used a postscript font, but you can adapt this to use ttf very easily.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112525852134308981?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112525852134308981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112525852134308981' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112525852134308981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112525852134308981'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/08/proving-human-existence-user.html' title='Proving human existence: user authentication images'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112515909640081977</id><published>2005-08-27T09:07:00.000-07:00</published><updated>2006-11-15T21:19:47.086-07:00</updated><title type='text'>PHP Image class</title><content type='html'>Hey everyone. I started to work with some image stuff today, and realized that I should allow members of this site that I'm working on to upload an image that doesn't meet the specs that my software needs. Now, that's an obvious thing that needs to be added to any site that lets it's users play with images, heck, any site that has a member base should allow the user to upload images (forums, community sites, comment sections, etc...). I'm not going to go into the uploading images aspect of PHP, at least today anyway, but I did just write something you might find useful... An image class... The main purpose is to allow a simple resize, but I'm sure you could write some classes that extend the functionality of this one.&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;/*&lt;br /&gt; * Basic PHP Image class&lt;br /&gt; * Copyright (C) 2005 James Kassemi&lt;br /&gt; * &lt;br /&gt; * This library is free software; you can redistribute it and/or&lt;br /&gt; * modify it under the terms of the GNU Lesser General Public&lt;br /&gt; * License as published by the Free Software Foundation; either&lt;br /&gt; * version 2.1 of the License, or (at your option) any later version.&lt;br /&gt;&lt;br /&gt; * This library is distributed in the hope that it will be useful,&lt;br /&gt; * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU&lt;br /&gt; * Lesser General Public License for more details.&lt;br /&gt;&lt;br /&gt; * You can view the LGPL here: http://www.gnu.org/licenses/lgpl.html&lt;br /&gt; * &lt;br /&gt; * Requirements:&lt;br /&gt; *   &lt;br /&gt; *   PHP with compiled gd library&lt;br /&gt; * &lt;br /&gt; * Description:&lt;br /&gt; * &lt;br /&gt; *   Very simple class for dealing with images. Main purpose was for simple resize. &lt;br /&gt; * &lt;br /&gt; * Functions:&lt;br /&gt; * &lt;br /&gt; *   set_image(string $path)&lt;br /&gt; *    start off by setting the path to the starter image.&lt;br /&gt; * &lt;br /&gt; *   image_type()&lt;br /&gt; *    returns the type of the image in plain text.&lt;br /&gt; * &lt;br /&gt; *   create_image_resource()&lt;br /&gt; *    creates a resource image based on the type of the image set using set_image()&lt;br /&gt; * &lt;br /&gt; *   resize($width, $height, $unit='px', $dest_x=0, $dest_y=0, $src_x=0, $src_y=0)&lt;br /&gt; *    resizes the image to a new image resource, which it returns.&lt;br /&gt; *     width =&gt; desired width after resize.&lt;br /&gt; *     height =&gt; desired height after resize.&lt;br /&gt; *     unit =&gt; Can be set to either px or %, adjusts size accordingly.&lt;br /&gt; *     dest_x =&gt; the starting x pixel on the resized image...&lt;br /&gt; *     dest_y =&gt; the starting y pixel on the resized image...&lt;br /&gt; *     src_x =&gt; the x pixel in which to start grabbing the source image...&lt;br /&gt; *     src_y =&gt; the y pixel in which to start grabbing the source image...&lt;br /&gt; * &lt;br /&gt; *  save($image, $filename, $quality=100, $type='')&lt;br /&gt; *   saves an image resource to a file&lt;br /&gt; *    image =&gt; the image resource to save&lt;br /&gt; *    filename =&gt; filename to save to.&lt;br /&gt; *    quality =&gt; for jpegs, adjust quality of file.&lt;br /&gt; *    type =&gt; specify the type (jpg, png, gif, wbmp)&lt;br /&gt; *     if none is specified, will use the type of the image set with set_image&lt;br /&gt; *&lt;br /&gt; *   output($image, $type='', $quality='100', $header=true&lt;br /&gt; *    outputs an image resources content to the browser&lt;br /&gt; *     image =&gt; the image resource to output&lt;br /&gt; *     type =&gt; the image type to output&lt;br /&gt; *     quality =&gt; for jpegs, adjust quality of output.&lt;br /&gt; *     header =&gt; true or false... Output the mime type... &lt;br /&gt; * &lt;br /&gt; *  Sample usage:&lt;br /&gt; * &lt;br /&gt; *  Takes the PHP logo from the php.net site, and resizes it to 200px by 200px&lt;br /&gt; *  &lt;br /&gt; *  &lt;br /&gt;     &lt;?php&lt;br /&gt;     include ('./class/image.php')&lt;br /&gt;      $image = new image();&lt;br /&gt;   $image-&gt;set_image('http://us2.php.net/images/php.gif');&lt;br /&gt;   $new = $image-&gt;resize(200, 200);&lt;br /&gt;   $image-&gt;output($new, 'jpg'); &lt;br /&gt;  ?&gt;&lt;br /&gt;  &lt;br /&gt;*/&lt;br /&gt;  &lt;br /&gt;class image {&lt;br /&gt; &lt;br /&gt; public $path;&lt;br /&gt; &lt;br /&gt; function set_image($path){&lt;br /&gt;  $this-&gt;path = $path; &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; function image_type(){&lt;br /&gt;  $type = getimagesize($this-&gt;path);&lt;br /&gt;  $type = $type[2];&lt;br /&gt;  switch($type){&lt;br /&gt;   case 1:&lt;br /&gt;    return "gif";&lt;br /&gt;   case 2: &lt;br /&gt;    return "jpg";&lt;br /&gt;   case 3:&lt;br /&gt;    return "png";&lt;br /&gt;   case 4:&lt;br /&gt;    return "swf";&lt;br /&gt;   case 5:&lt;br /&gt;    return "psd";&lt;br /&gt;   case 6:&lt;br /&gt;    return "bmp";&lt;br /&gt;   case 7:&lt;br /&gt;    return "tiff(intel)";&lt;br /&gt;   case 8:&lt;br /&gt;    return "tiff(motorola)";&lt;br /&gt;   case 9:&lt;br /&gt;    return "jpc";&lt;br /&gt;   case 10:&lt;br /&gt;    return "jp2";&lt;br /&gt;   case 11:&lt;br /&gt;    return "jpx";&lt;br /&gt;   case 12:&lt;br /&gt;    return "jb2";&lt;br /&gt;   case 13:&lt;br /&gt;    return "swc";&lt;br /&gt;   case 14 :&lt;br /&gt;    return "iff";&lt;br /&gt;   case 15:&lt;br /&gt;    return "wbmp";&lt;br /&gt;   case 16:&lt;br /&gt;    return "xbm";&lt;br /&gt;   default:&lt;br /&gt;    return false;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; function create_image_resource(){&lt;br /&gt;  /* This will convert the set image to the proper resource, so we can work with it. */&lt;br /&gt;  $type = $this-&gt;image_type();&lt;br /&gt;  switch($type){&lt;br /&gt;   case 'gif':&lt;br /&gt;    return imagecreatefromgif($this-&gt;path);&lt;br /&gt;   case 'jpg':&lt;br /&gt;    return imagecreatefromjpeg($this-&gt;path);&lt;br /&gt;   case 'png':&lt;br /&gt;    return imagecreatefrompng($this-&gt;path);&lt;br /&gt;   case 'wbmp':&lt;br /&gt;    return imagecreatefromwbmp($this-&gt;path);&lt;br /&gt;   default:&lt;br /&gt;    return false;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; function resize($width, $height, $unit='px', $dest_x=0, $dest_y=0, $src_x=0, $src_y=0){&lt;br /&gt;  $image_old = $this-&gt;create_image_resource();&lt;br /&gt;  $size = getimagesize($this-&gt;path);&lt;br /&gt;  $old_width = $size[0];&lt;br /&gt;  $old_height = $size[1];&lt;br /&gt;  switch($unit){&lt;br /&gt;   case 'px':&lt;br /&gt;    $new_width = $width;&lt;br /&gt;    $new_height = $height;&lt;br /&gt;    break;&lt;br /&gt;   case '%':&lt;br /&gt;    $width = $width / 100;&lt;br /&gt;    $height = $height / 100;&lt;br /&gt;    $new_width = $old_width * $height;&lt;br /&gt;    $new_height = $old_height * $height;&lt;br /&gt;    break;&lt;br /&gt;   default:&lt;br /&gt;    return false;&lt;br /&gt;  }&lt;br /&gt;  $image_new = imagecreatetruecolor($new_width, $new_height);&lt;br /&gt;  $success = imagecopyresampled($image_new, $image_old, $dest_x, $dest_y, $src_x, $src_y, $new_width, $new_height, &lt;br /&gt;     $old_width, $old_height);&lt;br /&gt;  return $image_new;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; function save($image, $filename, $quality='100', $type=''){&lt;br /&gt;  if($type=''){ $type=$this-&gt;image_type(); }&lt;br /&gt;  switch($type){&lt;br /&gt;   case 'gif':&lt;br /&gt;    imagegif($image, $filename);&lt;br /&gt;    return true;&lt;br /&gt;   case 'jpg':&lt;br /&gt;    imagejpeg($image, $filename);&lt;br /&gt;    return true;&lt;br /&gt;   case 'png':&lt;br /&gt;    imagepng($image, $filename);&lt;br /&gt;    return true;&lt;br /&gt;   case 'wbmp':&lt;br /&gt;    imagewbmp($image, $filename);&lt;br /&gt;    return true;&lt;br /&gt;   default:&lt;br /&gt;    return false;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; function output($image, $type='', $quality='100', $header=true){&lt;br /&gt;  if($type==''){ $type=$this-&gt;image_type(); }&lt;br /&gt;  switch($type){&lt;br /&gt;   case 'gif':&lt;br /&gt;    if($header==true)&lt;br /&gt;     header('Content-type: image/gif');&lt;br /&gt;    imagegif($image);&lt;br /&gt;    break;&lt;br /&gt;   case 'jpg':&lt;br /&gt;    if($header==true)     &lt;br /&gt;     header('Content-type: image/jpeg');&lt;br /&gt;    imagejpeg($image);&lt;br /&gt;    break;&lt;br /&gt;   case 'png':&lt;br /&gt;    if($header==true)     &lt;br /&gt;     header('Content-type: image/png');&lt;br /&gt;    imagepng($image);&lt;br /&gt;    break;&lt;br /&gt;   case 'wbmp':&lt;br /&gt;    if($header==true)     &lt;br /&gt;     header('Content-type: image/wbmp');&lt;br /&gt;    imagewbmp($image);&lt;br /&gt;    break;&lt;br /&gt;   default:&lt;br /&gt;    return false;&lt;br /&gt;  }  &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;?&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112515909640081977?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112515909640081977/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112515909640081977' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112515909640081977'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112515909640081977'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/08/php-image-class.html' title='PHP Image class'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112506290941187054</id><published>2005-08-26T06:04:00.000-07:00</published><updated>2006-11-15T21:19:47.014-07:00</updated><title type='text'>Martial arts are geeky</title><content type='html'>I've been struggling with this one for a little over two weeks. I take martial arts. Does that make me a geek? The question was raised after I watched "Napoleon Dynamite," a movie which I don't really understand. How can a film written by an average joe high school student (I don't really know if it was, but there wasn't anything special in it) about a semi-surrealistic high school, an obviously imaginary disfunctional family, and a fully grown idiot be a success in the box office? Never mind. This is America. I'm not surprised.&lt;br /&gt;&lt;br /&gt;So I'm laboriously struggling through this film, and along comes the dojo visit. Inside the karate school are twiggy nerds, unsuccessful geeks and scrawny misfits listening to a redneck instructor screaming nonsense. I realize that this film was written by idiots, and would contain scenes that mirror their views on life. Several days passed, and one night I sat down in front of the television once more (I do waste my life away frequently), and a discovery channel show, "Is it Real?" popped up on the guide. I watched it, and along came a dojo scene. This one with a pot-bellied red-necked ball of a man who allegedly mastered the "chi no-touch knockout."&lt;br /&gt;&lt;br /&gt;After several demonstrations I took a look at the audience. To my amazement, it was very Napoleon Dynamitish. Dungeons and Dragons, Magic the Gathering and Star Trek are apparently still all the rage. So I burried my head in my hands and cried. I had given up such obsessions years ago... Was I still a geek? I decided to lay it out:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;&lt;tr style="font-weight:bold;"&gt;&lt;td&gt;Category&lt;/td&gt;&lt;td&gt;Geek&lt;/td&gt;&lt;td&gt;Normal&lt;/td&gt;&lt;td&gt;Me&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Style&lt;/td&gt;&lt;td&gt;"Got Root" T-Shirt/Jeans&lt;/td&gt;&lt;td&gt;Regular T-Shirt/Jeans&lt;/td&gt;&lt;td&gt;Down with SCO T-Shirt/Jeans&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Health&lt;/td&gt;&lt;td&gt;No Exercise&lt;/td&gt;&lt;td&gt;Football&lt;/td&gt;&lt;td&gt;Martial Arts&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Car&lt;/td&gt;&lt;td&gt;Volkswagon&lt;/td&gt;&lt;td&gt;Mustang&lt;/td&gt;&lt;td&gt;Stratus + No Gas&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Operating System&lt;/td&gt;&lt;td&gt;BSD&lt;/td&gt;&lt;td&gt;Windows&lt;/td&gt;&lt;td&gt;Linux&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Girl&lt;/td&gt;&lt;td&gt;Poster&lt;/td&gt;&lt;td&gt;Cheerleader/Blonde&lt;/td&gt;&lt;td&gt;Wallpaper&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Coming to Conclusions&lt;/td&gt;&lt;td&gt;Graphs&lt;/td&gt;&lt;td&gt;Conclusions?&lt;/td&gt;&lt;td&gt;Tables/Graphs&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;So. You add them up. I'm clearly not a geek... But I don't quite match the normal column, either. So what am I? I leave that to you... My non-existent audience...&lt;br /&gt;&lt;br /&gt;'Till next time everyone.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112506290941187054?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112506290941187054/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112506290941187054' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112506290941187054'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112506290941187054'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/08/martial-arts-are-geeky.html' title='Martial arts are geeky'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112488709565111171</id><published>2005-08-24T05:24:00.000-07:00</published><updated>2006-11-15T21:19:46.931-07:00</updated><title type='text'>Working with parents and children</title><content type='html'>Here's a quick little puzzle:&lt;br /&gt;&lt;br /&gt;You have a database that contains the following:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;id | parent | title            | description&lt;br /&gt;1     0       blah               blah&lt;br /&gt;2     1       blah subcat        Subcategory under the blah title.&lt;br /&gt;3     2       blah subcat subc   Subcategory under id 2&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This must be fairly common with category listings. The categories can be multi-leveled, a lot like the folder system on your hard drive (eg /, /usr, /usr/local, where /usr/local is a second level directory). The problem comes when you want to know what categories are children of the parent category to an unlimited number of levels. &lt;br /&gt;&lt;br /&gt;Since I don't know my SQL that well, I decided to use a simple PHP solution... It's obvious that this needs to be recursive. My worry is that when there are thousands of categories, the processing requirements for sorting through them will be too high. If you can think of something better, please post. Here's what I've got:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt; function get_all_children($category="0"){&lt;br /&gt;  $children = array();&lt;br /&gt;  $this-&gt;db-&gt;query(sprintf("select distinct id from categories where parent='%s'",&lt;br /&gt;     mysql_real_escape_string($category)));&lt;br /&gt;  &lt;br /&gt;  while($row = $this-&gt;db-&gt;fetch()){&lt;br /&gt;   $children[] = $row['id']; &lt;br /&gt;  }&lt;br /&gt;  $temp_array = array();&lt;br /&gt;  foreach($children as $child){&lt;br /&gt;   $temp_array=$this-&gt;get_all_children($child); &lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  $children = array_merge($children, $temp_array);&lt;br /&gt;  $children = array_unique($children);&lt;br /&gt;  array_unshift($children, $category);&lt;br /&gt;  return $children;&lt;br /&gt; }&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;There is a nice explaination here that recommends I don't store the data in this method, and instead suggests the Modified Preorder Tree Traversal method. But that really doesn't help someone who's already got a functional method for the simple parent method, and doesn't feel like modifying thousands of lines of code to get their program working faster. Argh. Wish I'd seen this earlier :)&lt;br /&gt;&lt;br /&gt;http://www.sitepoint.com/article/hierarchical-data-database/1&lt;br /&gt;&lt;br /&gt;Instead of changing everything right now, I've decided to run a cron job with my update procedure (which I will publish as soon as I'm no longer bound by confidentiality. Soon, I hope, as the project appears to be nearly done. &lt;br /&gt;&lt;br /&gt;Take it easy everyone.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112488709565111171?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112488709565111171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112488709565111171' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112488709565111171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112488709565111171'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/08/working-with-parents-and-children.html' title='Working with parents and children'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112488254185729545</id><published>2005-08-24T04:09:00.000-07:00</published><updated>2006-11-15T21:19:46.854-07:00</updated><title type='text'>Adopt good programming practice before it's too late</title><content type='html'>I've been programming now for as long as I can remember. If you can name the language, I've dabbled with it. My first programs were on my old Packard Bell 500, and written in C. They weren't written well, but I was eight, and I didn't care. So long as the system made a beep or I returned a list of numbers with a for loop, I was happy.&lt;br /&gt;&lt;br /&gt;When my neighbor learned that I was using the computer, they donated a Commodore, which I (despite the downgrade), I absolutely loved. I played text game after text game on it, and even attempted making my own. BASIC became my language of choice, as it was simple enough for me to fully understand. I didn't have to worry too much about strange syntax, and could always use the GOTO statements, which were so much easier than writing good code.&lt;br /&gt;&lt;br /&gt;My switch to BASIC from C has turned into the biggest mistake I ever made. Instead of becoming proficient with a powerful language, I turned to something that would make quick work of small projects. I gave up true programming for a while, and started working on web pages back in middle school. These days that doesn't seem like much, but this was when the internet was still it's fastest at 14.4 and none of my teachers even realized that it was possible for them to put up their own pages. I remember the shoddy interface of JKLinks, my collection of valuable internet resources, of which I wish I had a copy today. The JKLinks Award was sent out to many sites, none of which accepted the obvious advertising ploy. The site was a failure, as all of mine have been so far.&lt;br /&gt;&lt;br /&gt;Javascript was my next structured language, and with it I created a great menu system similar to the Windows start menu, but a year later a technology came out that made the system useless: CSS. Menus similar to what I programmed were (and are) popping up everywhere, and I had no chance of any type of commercial marketing - not that I was thinking of it.&lt;br /&gt;&lt;br /&gt;Some friends' parents took a look at what I had done with JKLinks, and decided they'd hire me to make their web pages. I was making fifty bucks here and there fairly regularly, and then another parent approached me. This one in real estate. I spent countless hours on site designs for her, none of which were good enough. In the end I received a check for $25.00 for my effort, and none of the pages were ever used. I gave up.&lt;br /&gt;&lt;br /&gt;During high school I explored mIRC and AOL chatroom 'servers'. I ditched mIRC when I was able to more reliably get content by the America Online method. I followed lead and started programming in Visual Basic. Another bad move. Luckily my time spent there didn't last long, and I quickly moved into Java, Delphi, C++ and currently, PHP.&lt;br /&gt;&lt;br /&gt;To get to the point though, which I understand you must be dying to hear right now, I'm having a hell of a time getting some of my programming done because of my lack of focus early on in my programming lifetime. When I was working with each of the languages that I'd learned, I was never doing anything too important. Never anything that was to be released and expected to run &lt;span style="font-style: italic;"&gt;well&lt;/span&gt;. Currently, though, I am working on an important project, the nature of which I cannot yet reveal. To get this project done, and done quickly, I heard I should use PHP with a mySQL database backend. The language was simple, much like C++, and very easy to work with. I started learning immediately, and felt I was doing fairly well.&lt;br /&gt;&lt;br /&gt;The problem? NEVER &lt;span style="font-style: italic;"&gt;start&lt;/span&gt; learning a programming language by programming what you're learning the language for. Let me qualify. NEVER for a program that you need to have running well, and NEVER for a very large program. I'm currently at the 52MB mark in code. And I just came across I huge problem that I need to fix with the code I started writing as I was learning. It's so sloppy and bug-ridden that it will take me weeks to fix it. That's my advice to you today. I know, promising introductory story, weak conclusion. Any of you with any more universal programming advice, feel free to comment here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112488254185729545?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112488254185729545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112488254185729545' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112488254185729545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112488254185729545'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/08/adopt-good-programming-practice-before.html' title='Adopt good programming practice before it&apos;s too late'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15695660.post-112477227653088831</id><published>2005-08-22T21:21:00.000-07:00</published><updated>2006-11-15T21:19:46.769-07:00</updated><title type='text'>Acrobat Reader and why I hate Windows</title><content type='html'>First off, hello there. This is my first entry. And I'm happy to be joining the world of blogs. There are a few things that I've wanted to talk about for a while now, but can't (project confidentiality agreements), and decided I can do a pretty good job of blabbing away with the non-confidential things for now.&lt;br /&gt;&lt;br /&gt;Linux is my operating system of choice. I started using it a little over a year ago, and have currently gotten to the point that I can use it for everything I used my old Windows boxes for. Unfortunately I'm in the process of cleaning out my main computer (hp ze4420us laptop), and am using a Windows machine to try to open the service manual. It's a pdf. A very simple pdf.&lt;br /&gt;&lt;br /&gt;I placed the file on a USB flash drive before unplugging my laptop, and tried to gain access to that file from this system, running a clean install of Windows 2000. Since there are no pdf readers installed by default, I went over to adobe.com, and clicked "Get Acrobat Reader." The site detected that I was running Windows 2000, and asked me which version I wanted to download. I downloaded the appropriate file, and attempted to install. After 30 minutes (slow machine), the Netopsystems FEAD Optimizer finished "recomposing" some strange data, and I was then told that this machine did not support the version of Reader I had downloaded, and that I would need to update.&lt;br /&gt;&lt;br /&gt;An hour later I finished a Windows Update, and tried to run the setup application again. Instead of quickly telling me that everything would be alright, and that the program had been installed, I instead am met again with the Netopsystems FEAD Optimizer, which runs slower than ever.&lt;br /&gt;&lt;br /&gt;Now. My experience with pdf's on linux has been quite different. After a default slackware installation, I am able to launch X, and open a pdf file with gv or kpdf, or any of the other wonderful tools that are immediately available. I find it funny that an entire OS+ every tool you would ever need and more fit on just two CDs, but for a functional Windows installation I need to install hundreds of different applications.&lt;br /&gt;&lt;br /&gt;Let's now examine the message that I just got on my computer: "This version of Adobe Acrobat will only run on Windows 2000 SP2". That's funny, since I just updated to SP1, and downloaded the SP1 edition of Acrobat. Anyway, let me get yet another adobe download. I'll be right back.&lt;br /&gt;&lt;br /&gt;Okay. I just downloaded the proper installer downloading tool. What happened to the good old days when I didn't have to mess around with these downloading tools. I'd much rather just download the file by my own methods. I think my problem with such tools is that they automatically assume I know less than I do. Why allow somebody who doesn't know how to download the proper file from the fastest mirror install something on their computer?&lt;br /&gt;&lt;br /&gt;Let's say for a moment that slackware didn't come with a pdf reader. Would I be going through the same things here? No. Here's why. With every slackware installation I have, I always install slapt-get (and use apt-get for debian systems). All I would need to do would be&lt;br /&gt;&lt;br /&gt;$ slapt-get --install kpdf&lt;br /&gt;or&lt;br /&gt;$ slapt-get --install gv&lt;br /&gt;&lt;br /&gt;And I would immediately have the proper package. If no such package existed, I would only need to download a VERY small (in comparison) file, and set it to compile with a ./configure, make and make install. The process doesn't take nearly as long as this has so far, and I get a software build optimized for my computer's architecture.&lt;br /&gt;&lt;br /&gt;I'm back at the Netopsystems FEAD Optimizer. The third time. And I'm pretty much done ranting. I'll be back to bitch about more later :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15695660-112477227653088831?l=kassemi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kassemi.blogspot.com/feeds/112477227653088831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15695660&amp;postID=112477227653088831' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112477227653088831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15695660/posts/default/112477227653088831'/><link rel='alternate' type='text/html' href='http://kassemi.blogspot.com/2005/08/acrobat-reader-and-why-i-hate-windows.html' title='Acrobat Reader and why I hate Windows'/><author><name>tweekgeek</name><uri>http://www.blogger.com/profile/14633355606378040586</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
