<?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-2044427065375438750</id><updated>2012-02-03T05:31:47.952-08:00</updated><category term='proxy'/><category term='LDIF'/><category term='xmlsec'/><category term='Outlook'/><category term='Postfix'/><category term='timeouts'/><category term='curl'/><category term='rewrite'/><category term='standalone'/><category term='Eye-Fi'/><category term='python'/><category term='EyeFi'/><category term='windows'/><category term='pkg_add'/><category term='backup'/><category term='linux'/><category term='file transfer'/><category term='GAL'/><category term='obex'/><category term='SSH'/><category term='tutorial'/><category term='microsoft office communicator'/><category term='FreeBSD'/><category term='CSV'/><category term='Split Delivery'/><category term='Converting LDIF to CSV'/><category term='views.py'/><category term='wordpress'/><category term='LDAP'/><category term='LDIF to CSV'/><category term='tcp'/><category term='bluetooth'/><category term='libxml'/><category term='urls.py'/><category term='Django'/><category term='Active Directory'/><category term='unix'/><category term='BaseHTTPServer'/><category term='mod_rewrite'/><category term='server'/><category term='compiling'/><category term='pyxmlsec'/><category term='SiteMinder'/><category term='ubuntu'/><category term='Github'/><category term='libcurl'/><category term='getmail'/><category term='Google Apps'/><category term='gmail'/><title type='text'>Return Boolean True</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>26</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-7082756300136292492</id><published>2011-10-27T11:52:00.000-07:00</published><updated>2011-10-27T14:36:04.790-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='backup'/><category scheme='http://www.blogger.com/atom/ns#' term='gmail'/><category scheme='http://www.blogger.com/atom/ns#' term='getmail'/><title type='text'>Backing up and Archiving Google Mail Accounts</title><content type='html'>The easiest way to backup Google Mail accounts is to enable IMAP on the account and download the messages using &lt;a href="http://pyropus.ca/software/getmail/"&gt;getmail&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Once getmail is installed you need to create a file called getmailrc. If you plan to download multiple gmail accounts then you might want to create a directory for each account and point the getmail script to that directory. Here is an example of a getmailrc file for Google Mail:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;[retriever]&lt;br /&gt;type = SimpleIMAPSSLRetriever&lt;br /&gt;server = imap.gmail.com&lt;br /&gt;username = username@example.com&lt;br /&gt;password = examplepassword&lt;br /&gt;mailboxes = ("[Gmail]/All Mail",)&lt;br /&gt;port = 993&lt;br /&gt;&lt;br /&gt;[destination]&lt;br /&gt;type = Maildir&lt;br /&gt;path = ~/username@example.com/&lt;br /&gt;&lt;br /&gt;[options]&lt;br /&gt;received = false&lt;br /&gt;delivered_to = false&lt;br /&gt;read_all = false&lt;br /&gt;verbose = 1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;After this file is saved you can procede to run getmail. I needed getmail to run all night and in the background. I outputted all the stdout to a logfile so I used the following command:&lt;br /&gt;&lt;br /&gt;getmail --getmaildir . &gt; output.txt 2&gt;&amp;1 &amp;&lt;br /&gt;&lt;br /&gt;Don't forget to create the directories cur, new, tmp as these are the directories that are needed for IMAP.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now that you have your mail in a Maildir format what do you do with it? In my case I wanted to delete the account off Google Apps but still be able to search the mail if I needed it at a later date. &lt;br /&gt;&lt;br /&gt;The strategy I came up with to bring up a copy of courier and serve the Maildir using a webmail script (in this case Roundcube).&lt;br /&gt;&lt;br /&gt;I installed PHP through Nginx first. The easiest way to get a PHP environment up and running on Nginx is to use the Ubuntu packages:&lt;br /&gt;&lt;br /&gt;php5-cgi &lt;br /&gt;php5-common&lt;br /&gt;&lt;br /&gt;For additional functionality such as PostgreSQL support you can install the package:&lt;br /&gt;php5-pgsql&lt;br /&gt;&lt;br /&gt;I then configured nginx with the following script:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;server {&lt;br /&gt;  listen      80;&lt;br /&gt;  server_name webmail.example.com;&lt;br /&gt;  access_log  /var/log/nginx/access.log;&lt;br /&gt;  log_subrequest off;&lt;br /&gt;&lt;br /&gt;  location / {&lt;br /&gt;    root /www/webmail.example.com;&lt;br /&gt;    index index.php;&lt;br /&gt;&lt;br /&gt;    location ~ \.php$ {&lt;br /&gt;      include        fastcgi_params;&lt;br /&gt;      fastcgi_pass   localhost:9000;&lt;br /&gt;      fastcgi_param  SCRIPT_FILENAME  /www/webmail.example.com/$fastcgi_script_name;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;I then created the script: /etc/init.d/php-fcgi&lt;br /&gt;BIND=127.0.0.1:9000&lt;br /&gt;USER=www-data&lt;br /&gt;PHP_FCGI_CHILDREN=15&lt;br /&gt;PHP_FCGI_MAX_REQUESTS=1000&lt;br /&gt; &lt;br /&gt;PHP_CGI=/usr/bin/php-cgi&lt;br /&gt;PHP_CGI_NAME=`basename $PHP_CGI`&lt;br /&gt;PHP_CGI_ARGS="- USER=$USER PATH=/usr/bin PHP_FCGI_CHILDREN=$PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS=$PHP_FCGI_MAX_REQUESTS $PHP_CGI -b $BIND"&lt;br /&gt;RETVAL=0&lt;br /&gt;&lt;br /&gt;start() {&lt;br /&gt;      echo -n "Starting PHP FastCGI: "&lt;br /&gt;      start-stop-daemon --quiet --start --background --chuid "$USER" --exec /usr/bin/env -- $PHP_CGI_ARGS&lt;br /&gt;      RETVAL=$?&lt;br /&gt;      echo "$PHP_CGI_NAME."&lt;br /&gt;}&lt;br /&gt;stop() {&lt;br /&gt;      echo -n "Stopping PHP FastCGI: "&lt;br /&gt;      killall -q -w -u $USER $PHP_CGI&lt;br /&gt;      RETVAL=$?&lt;br /&gt;      echo "$PHP_CGI_NAME."&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;case "$1" in&lt;br /&gt;    start)&lt;br /&gt;      start&lt;br /&gt;  ;;&lt;br /&gt;    stop)&lt;br /&gt;      stop&lt;br /&gt;  ;;&lt;br /&gt;    restart)&lt;br /&gt;      stop&lt;br /&gt;      start&lt;br /&gt;  ;;&lt;br /&gt;    *)&lt;br /&gt;      echo "Usage: php-fastcgi {start|stop|restart}"&lt;br /&gt;      exit 1&lt;br /&gt;  ;;&lt;br /&gt;esac&lt;br /&gt;exit $RETVAL&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;After php was up and running I installed courier:&lt;br /&gt;apt-get install courier-imap courier-imap-ssl&lt;br /&gt;&lt;br /&gt;I then downloaded roundcube and configured roundcube as necessary.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-7082756300136292492?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/7082756300136292492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=7082756300136292492' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/7082756300136292492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/7082756300136292492'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2011/10/backing-up-and-archiving-google-mail.html' title='Backing up and Archiving Google Mail Accounts'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-2771984039591762606</id><published>2011-10-19T10:57:00.000-07:00</published><updated>2011-10-19T11:24:33.334-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Split Delivery'/><category scheme='http://www.blogger.com/atom/ns#' term='Postfix'/><category scheme='http://www.blogger.com/atom/ns#' term='Google Apps'/><title type='text'>Google Apps Split Delivery for Email - Have your cake and eat it too</title><content type='html'>Split delivery for e-mail is when you have a single piece of mail but want a copy of it sent to multiple destinations. There are a couple of reasons you would want to do this:&lt;br /&gt;&lt;br /&gt;- You are getting ready to migrate to Google Apps but don't want to go all in yet with your current e-mail server. This is understandable since you want to test out Google Apps first to see if it will work.&lt;br /&gt;&lt;br /&gt;- You like Google Apps but don't want to pay the yearly fee. You rather just stay under the limit of the free accounts but still want to have e-mail accounts on your domain (i.e. @example.com).&lt;br /&gt;&lt;br /&gt;- You have other special circumstances where you want a copy of all the mail that comes in and have it delivered to some other server.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This post is actually more toward the 2nd point. 90% of my e-mails are on Google Apps but there is a remaining 10% that I rather not have a Google Apps account. However I still want them to have e-mail via some webmail client.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;To get this working I am using Ubuntu with Postfix running the primary mail server for example.com. I set the MX records for example.com to this:&lt;br /&gt;10 mail.example.com&lt;br /&gt;20 ALT1.ASPMX.L.GOOGLE.COM&lt;br /&gt;&lt;br /&gt;Pretty straight forward so far. The trick is that you need to get Postfix to forward a copy of all Google Apps mail to their mail servers. To do this I use Postfix's Before-Queue Content Filter: &lt;a href="http://www.postfix.org/SMTPD_PROXY_README.html"&gt;http://www.postfix.org/SMTPD_PROXY_README.html&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This allows me to create a SMTP server that Postfix will delivery a copy of the mail to Google Apps. In the file /etc/postfix/master.cf I put the following at the end:&lt;br /&gt;&lt;br /&gt;# =============================================================&lt;br /&gt;# service type  private unpriv  chroot  wakeup  maxproc command&lt;br /&gt;#               (yes)   (yes)   (yes)   (never) (100)&lt;br /&gt;# =============================================================&lt;br /&gt;#&lt;br /&gt;# Before-filter SMTP server. Receive mail from the network and&lt;br /&gt;# pass it to the content filter on localhost port 10025.&lt;br /&gt;#&lt;br /&gt;smtp      inet  n       -       n       -       20      smtpd&lt;br /&gt;  -o smtpd_proxy_filter=127.0.0.1:10025&lt;br /&gt;  -o smtpd_client_connection_count_limit=10&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This makes Postfix delivery a copy of the incoming mail to the SMTP server at  127.0.0.1:10025.&lt;br /&gt;&lt;br /&gt;Okay but now you are asking where do I get an SMTP server to do the processing? It so happens Python comes with a smtp server library. I wrote a script that basicallyhttp://www.blogger.com/img/blank.gif inherits the SMTPServer (called CustomSMTPServer). It also implements the one command that is expected by Postfix (EHLO) because Postfix actually speaks ESMTP. I did this by subclassing the smtpd.SMTPChannel class. One caveat is that I had to use the _SMTPChannel__variablename syntax because some variables like fqdn and greeting were made private by the SMTPChannel class. So with Python you use the special syntax of prepending the class name to access it. This is generally bad practice but in this case it was all I had.&lt;br /&gt;&lt;br /&gt;You can download the script here:&lt;br /&gt;&lt;a href="http://dl.dropbox.com/u/2177278/pymailforwarder.py"&gt;http://dl.dropbox.com/u/2177278/pymailforwarder.py&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Simply run the script to start a basic SMTP server listening on port 10025 and localhost. The script simply accepts a piece of mail and forwards it to Google App's mail server.&lt;br /&gt;&lt;br /&gt;So what does this let you do? In my case this lets me run Roundcube, Horde, or SquirrelMail for users that don't need a Google Apps e-mail account. For those that do I simply create that user on Google Apps.&lt;br /&gt;&lt;br /&gt;Things to watch out for with this type of deployment:&lt;br /&gt;&lt;br /&gt;- You have to edit /etc/postfix/main.cf and add the value&lt;br /&gt;local_recipient_maps =&lt;br /&gt;(Yes that is a blank or equals nothing). This makes Postfix accept the mail even though the recipient is not in the list. This can be bad. Postfix says this in the documentation:&lt;br /&gt;&lt;br /&gt;With this setting, the Postfix SMTP server will not reject mail with "User unknown in local recipient table". Don't do this on systems that receive mail directly from the Internet. With today's worms and viruses, Postfix will become a backscatter source: it accepts mail for non-existent recipients and then tries to return that mail as "undeliverable" to the often forged sender address. &lt;br /&gt;&lt;br /&gt;To get around this you should really have an alias map file. For temporary testing though this setting will work wonders.&lt;br /&gt;&lt;br /&gt;- The Python SMTP relay should not be exposed to the internet. It listens on localhost but ideally it would be nice to modify the script to accept authentication of some sort.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-2771984039591762606?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/2771984039591762606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=2771984039591762606' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/2771984039591762606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/2771984039591762606'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2011/10/google-apps-split-delivery-for-email.html' title='Google Apps Split Delivery for Email - Have your cake and eat it too'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-2220337126098547308</id><published>2011-10-16T21:09:00.001-07:00</published><updated>2011-10-16T21:10:37.396-07:00</updated><title type='text'>Locales in Ubuntu</title><content type='html'>The list of locales that you have installed on a system are in the directory:&lt;br /&gt;&lt;br /&gt;/usr/lib/locale&lt;br /&gt;&lt;br /&gt;To generate a locale you can run:&lt;br /&gt;&lt;br /&gt;locale-gen en_US.UTF-8&lt;br /&gt;&lt;br /&gt;This is very useful when you need to generate a UTF-8 locale.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-2220337126098547308?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/2220337126098547308/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=2220337126098547308' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/2220337126098547308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/2220337126098547308'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2011/10/locales-in-ubuntu.html' title='Locales in Ubuntu'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-2088929103130237255</id><published>2011-10-13T14:17:00.000-07:00</published><updated>2011-10-13T14:22:48.425-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='microsoft office communicator'/><title type='text'>Microsoft Office Communicator - Problem verifying certificate from the server.</title><content type='html'>When using Microsoft Office Communicator with a server that has TLS enabled you might get an error message "Problem verifying certificate from the server.".&lt;br /&gt;&lt;br /&gt;This message means that the computer you are on does not trust the certificate that is being presented to it.&lt;br /&gt;&lt;br /&gt;The first way to troubleshoot this is to figure out what certificate it is receiving. The easiest way I've found to do this is to use openssl's s_client:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;openssl s_client -connect lcs.example.com:5061&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;By doing this you will see the entire certificate chain. You now need to go into the windows certificate management tools and make sure that chain is valid.&lt;br /&gt;&lt;br /&gt;Generally this will involve running mmc.exe, then adding the snap in "Certificate Management" for the computer itself.&lt;br /&gt;&lt;br /&gt;Another option is to cut and paste the BEGIN and END certificate lines into a text file. Name the text file with a .der extension and install the certificate. Then browse to the certificate in MMC and see if anything is wrong. Things that might go wrong include the validity date or being unable to trust the certificate chain (most likely from missing certificates).&lt;br /&gt;&lt;br /&gt;If you are missing certificates you need to track them down and install them. After this is done you should be able to connect to communicator server.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-2088929103130237255?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/2088929103130237255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=2088929103130237255' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/2088929103130237255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/2088929103130237255'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2011/10/microsoft-office-communicator-problem.html' title='Microsoft Office Communicator - Problem verifying certificate from the server.'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-982926555000637490</id><published>2011-10-12T18:52:00.000-07:00</published><updated>2011-10-12T18:53:37.911-07:00</updated><title type='text'>Getting Around the YouTube Duplicate Content Filter</title><content type='html'>I was recently trying to upload a video to YouTube but kept getting the Rejected (duplicate upload) message.&lt;br /&gt;&lt;br /&gt;I found the easiest way to get around this is to change the metadata on the video you are trying to upload. In my case it was an mp4 video.&lt;br /&gt;&lt;br /&gt;To change the metadata I used a program called AtomicParley:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://atomicparsley.sourceforge.net/"&gt;http://atomicparsley.sourceforge.net/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;After downloading it simply run&lt;br /&gt;&lt;br /&gt;AtomicParsley.exe "example.mp4" --artist "Me"&lt;br /&gt;&lt;br /&gt;Or whatever artist you want. The new file will be written out with new metadata. This should then pass any YouTube duplicate content check.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-982926555000637490?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/982926555000637490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=982926555000637490' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/982926555000637490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/982926555000637490'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2011/10/getting-around-youtube-duplicate.html' title='Getting Around the YouTube Duplicate Content Filter'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-5570985819784202144</id><published>2011-10-05T09:40:00.001-07:00</published><updated>2011-10-05T09:56:48.779-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wordpress'/><category scheme='http://www.blogger.com/atom/ns#' term='mod_rewrite'/><category scheme='http://www.blogger.com/atom/ns#' term='rewrite'/><title type='text'>Wordpress htaccess</title><content type='html'>One of my friends recently had a desire to rewrite some URLs with a Wordpress installation. The theme they were using was called Solid-WP and it supported a concept called "Projects". When you create a new project it actually gives it the URL&lt;br /&gt;&lt;br /&gt;http://www.example.com/project/&lt;name&gt;&lt;br /&gt;&lt;br /&gt;However there was a requirement that the URL should be renamed to http://www.example.com/apps/&lt;name&gt;.&lt;br /&gt;&lt;br /&gt;To do this I broke out mod_rewrite. Wordpress has some default rewrites stored inside .htaccess. Here is what it looks like:&lt;br /&gt;&lt;br /&gt;# BEGIN WordPress&lt;br /&gt;&lt;IfModule mod_rewrite.c&gt;&lt;br /&gt;RewriteEngine On&lt;br /&gt;&lt;br /&gt;RewriteBase /&lt;br /&gt;RewriteRule ^index\.php$ - [L]&lt;br /&gt;RewriteCond %{REQUEST_FILENAME} !-f&lt;br /&gt;RewriteCond %{REQUEST_FILENAME} !-d&lt;br /&gt;RewriteRule . /index.php [L]&lt;br /&gt;&lt;/IfModule&gt;&lt;br /&gt;&lt;br /&gt;# END WordPress&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Rewrite can be hard to understand so I wanted to breakdown exactly what Wordpress was doing. First line turns on the Rewrite engine and 2nd line is used to define a base URL for rewrites.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;RewriteRule ^index\.php$ - [L]&lt;br /&gt;&lt;br /&gt;If there is a request for /index.php then don't do any rewriting and just end processing right here (the L flag).&lt;br /&gt;&lt;br /&gt;RewriteCond %{REQUEST_FILENAME} !-f&lt;br /&gt;RewriteCond %{REQUEST_FILENAME} !-d&lt;br /&gt;&lt;br /&gt;These rewrite conditions are to test for real files and directories. Basically we don't want to rewrite a URL if the URL points to a directory or file. We just want to serve the file up. !-f tests whether or not the file exists and !-d tests whether or not the directory exists.&lt;br /&gt;&lt;br /&gt;RewriteRule . /index.php [L]&lt;br /&gt;&lt;br /&gt;This last line as I understand it rewrites all requests to index.php.&lt;br /&gt;&lt;br /&gt;What I ended up adding was this:&lt;br /&gt;&lt;br /&gt;&lt;IfModule mod_rewrite.c&gt;&lt;br /&gt;RewriteEngine On&lt;br /&gt;&lt;br /&gt;RewriteRule project/(.+) /apps/$1 [L,R]&lt;br /&gt;RewriteRule apps/(.+) /example-wp/index.php/project/$1/ [L]&lt;br /&gt;&lt;br /&gt;RewriteBase /&lt;br /&gt;RewriteRule ^index\.php$ - [L]&lt;br /&gt;RewriteCond %{REQUEST_FILENAME} !-f&lt;br /&gt;RewriteCond %{REQUEST_FILENAME} !-d&lt;br /&gt;RewriteRule . /index.php [L]&lt;br /&gt;&lt;/IfModule&gt;&lt;br /&gt;&lt;br /&gt;The first time a user might hit /project/example. They would hit the first rule and get redirected. Processing would stop.&lt;br /&gt;&lt;br /&gt;The second time a user hit the URL it would say /apps/example which would trigger the 2nd rule. It would get rewritten to the long form of WordPress's controller action.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-5570985819784202144?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/5570985819784202144/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=5570985819784202144' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/5570985819784202144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/5570985819784202144'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2011/10/wordpress-htaccess.html' title='Wordpress htaccess'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-6186641860134266807</id><published>2011-01-20T17:42:00.000-08:00</published><updated>2011-01-20T17:52:34.625-08:00</updated><title type='text'>Designing Good Web APIs</title><content type='html'>I am not going to claim eons of experience in designing good APIs. I am going to approach it from the background of a developer who has to use and integrate with them.&lt;br /&gt;&lt;br /&gt;What makes a good API? Here are some of my tenets:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;1. Make your API calls as RESTful-like as possible&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Because this term has evolved quite a bit I am going to stick with the primarily principles. Make API calls nouns describing "what" and not "do something".&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;2. API calls should have defaults.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Don't give me 100 required parameters just to see some action. Try as hard as you can to give me a basic call so I know I am doing something right. Along with this is to keep a minimum of API calls. The more calls you have documented the more I have to figure out which one it is I am suppose to be calling to get the right information. This is an area where I actually do want to be spoon-fed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;3. Use HTTP basic over SSL for authentication.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you have the time and energy also support OAuth. The reason I hesitate with going straight to OAuth is because if you are just building an API your resources are probably limited. You are going to make mistakes. Getting it up and running with the lowest (and secure) common denominator is key.&lt;br /&gt;&lt;br /&gt;Also use dedicated API keys that consist of an ID and a shared secret. Make sure these can be rolled.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;4. Make your return format JSON.&lt;/span&gt;&lt;br /&gt;For the love of god please don't use XML. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;5. Version your API call in the end point:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;/api/1.0/user/3&lt;br /&gt;/api/2.0/user/3&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;6. Make the calls easily testable.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To me this means I can plug it into a web browser, type in some credentials, and get a response back. As a developer this makes me feel good early on.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;7. Document your API calls with examples.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Especially the ones where I can click on a link and it does an API call for me. This is also great for testing your call.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;A number of these guidelines are geared heavily to web development. If you are designing an API for a message passing system with latency and size requirements a good deal of this would change.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-6186641860134266807?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/6186641860134266807/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=6186641860134266807' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6186641860134266807'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6186641860134266807'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2011/01/designing-good-web-apis.html' title='Designing Good Web APIs'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-1206809098165836786</id><published>2010-11-14T21:22:00.001-08:00</published><updated>2010-11-14T21:35:29.829-08:00</updated><title type='text'>How to get a 2yr single root SSL certificate for $10</title><content type='html'>I recently had to do some shopping for a SSL certificate for my startup &lt;a href="https://www.stratismo.com/"&gt;Stratismo&lt;/a&gt; (I linked to it incase anyone wants to see the actual certificate). Obviously I wanted one that was widely supported and didn't really want to pay a ridiculous amount for it.&lt;br /&gt;&lt;br /&gt;So shopping around I landed on RapidSSL's site.  RapidSSL has a program where you can switch to them if you have a competitor's certificate. On top of that they also give you a free year. All of this for free. The program details are here:&lt;br /&gt;&lt;br /&gt;&lt;a href=" http://www.rapidssl.com/switch-ssl/index.html"&gt;http://www.rapidssl.com/switch-ssl/index.html&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I just happened to have a Comodo certificate so I gave this a test run. The Comodo certificate had some issues because of the number of intermediate certificates I had to include. While this shouldn't cause problems in theory in reality it is just one more thing to deal with.&lt;br /&gt;&lt;br /&gt;So what I did was apply for RapidSSL. They ended up giving me one of their SSL certificates for free after verifying I had a Comodo SSL certificate. They also extended the validation by a year so basically I got two years for $10. RapidSSL certificates are also signed by Equifax which is installed on almost every browser.&lt;br /&gt;&lt;br /&gt;Overall a great deal.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-1206809098165836786?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/1206809098165836786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=1206809098165836786' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/1206809098165836786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/1206809098165836786'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2010/11/how-to-get-2yr-single-root-ssl.html' title='How to get a 2yr single root SSL certificate for $10'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-8476133849519411923</id><published>2009-07-13T15:27:00.001-07:00</published><updated>2009-07-13T16:18:25.142-07:00</updated><title type='text'>PySAML - A SAML 2.0 Toolkit for Python</title><content type='html'>Security Assertion Markup Language (SAML) can be a bit confusing to understand. At its core SAML is just a protocol with defined messages written in XML. The main purpose of SAML is to enable you to log in at one place such as a website and then jump over to another website without having to log in again. This setup is commonly called "federation".&lt;br /&gt;&lt;br /&gt;It is similiar to OAuth. I see SAML continuing to make headroom in the enterprise space while OAuth stays strong in the consumer space. However in the future I hope these two technologies will end up playing well together.&lt;br /&gt;&lt;br /&gt;In either case I am releasing a small Python library for generating SAML assertions. The main purpose of this is to learn SAML by doing (actually having to create an assertion gives me a good idea of the complexity of the protocol).&lt;br /&gt;&lt;br /&gt;The library depends on M2Crypto so download and install it:&lt;br /&gt;http://chandlerproject.org/bin/view/Projects/MeTooCrypto&lt;br /&gt;&lt;br /&gt;M2Crypto depends on SWIG so you might need that as well.&lt;br /&gt;&lt;br /&gt;Once that is installed you can download my distribution of PySAML here:&lt;br /&gt;&lt;br /&gt;Python 2.6 - Win32:&lt;br /&gt;&lt;a href="http://darkeneddesire.com/PySAML/PySAML-1.0.win32.exe"&gt;http://darkeneddesire.com/PySAML/PySAML-1.0.win32.exe&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;Unix (source):&lt;br /&gt;&lt;a href="http://darkeneddesire.com/PySAML/PySAML.tar.gz"&gt;http://darkeneddesire.com/PySAML/&lt;/a&gt;&lt;a href="http://darkeneddesire.com/PySAML/PySAML.tar.gz"&gt;PySAML.tar.gz&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;For windows you just run the executable. For unix you should run the following commands:&lt;br /&gt;&lt;br /&gt;# cd PySAML&lt;br /&gt;# python setup.py build&lt;br /&gt;# python setup.by install&lt;br /&gt;&lt;br /&gt;There are examples in the "examples" folder if you download the full source.&lt;br /&gt;&lt;br /&gt;The whole project is available on github as well:&lt;br /&gt;&lt;a href="http://http//github.com/tachang/PySAML/tree/master"&gt;http://github.com/tachang/PySAML/tree/master&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-8476133849519411923?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/8476133849519411923/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=8476133849519411923' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/8476133849519411923'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/8476133849519411923'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2009/07/pysaml-saml-20-toolkit-for-python.html' title='PySAML - A SAML 2.0 Toolkit for Python'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-7783286046602603292</id><published>2009-07-09T18:18:00.000-07:00</published><updated>2009-07-09T20:50:34.581-07:00</updated><title type='text'>Trying to get Dual-SIM to work in T-Mobile G1</title><content type='html'>There is a product being sold called "Magic SIM".&lt;br /&gt;&lt;br /&gt;http://www.magicsim.com/en/dual_sim_show.asp?id=49&amp;amp;cp_id=&amp;amp;sort2name=14&lt;br /&gt;&lt;br /&gt;Basically it is a SIM card that has two slots and a small memory chip. After physically cutting up your two SIM cards and putting them into the slots you insert the whole thing into your phone.&lt;br /&gt;&lt;br /&gt;If your phone supports the GSM STK (SIM Tool Kit) standard then you can switch back and forth between the two SIM cards.&lt;br /&gt;&lt;br /&gt;However for your phone to actually support the standard the manufacturer had to have built it into the operating system as well as provide a tool to "talk" using the STK.&lt;br /&gt;&lt;br /&gt;I currently see that the Android development  tree has some Stk development going on. I downloaded a precompiled Stk.apk and installed it on my phone with the card. However it does not seem to work.&lt;br /&gt;&lt;br /&gt;While I do see the SIM Toolkit menu icon and it does seem to read from the custom card I am unable to obtain a carrier signal from either of my SIM cards. When I scroll to any of the menu options such as "SIM 1" or "SIM 2" and press the trackball the phone simply gives me a rotating circle on the upper right saying it is busy. And at that point it hangs.&lt;br /&gt;&lt;br /&gt;Here is a quick and dirty image of my phone as well as what the SIM menu looks like:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_D1ngxQVNLdM/Sla6JNg2d1I/AAAAAAAABgc/FO4iW5FK27I/s1600-h/CIMG1878.JPG"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_D1ngxQVNLdM/Sla6JNg2d1I/AAAAAAAABgc/FO4iW5FK27I/s320/CIMG1878.JPG" alt="" id="BLOGGER_PHOTO_ID_5356673474212820818" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_D1ngxQVNLdM/Sla6YR7v5hI/AAAAAAAABgk/3lG9UZkp81U/s1600-h/CIMG1879.JPG"&gt;&lt;img style="cursor: pointer; width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_D1ngxQVNLdM/Sla6YR7v5hI/AAAAAAAABgk/3lG9UZkp81U/s320/CIMG1879.JPG" alt="" id="BLOGGER_PHOTO_ID_5356673733097416210" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-7783286046602603292?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/7783286046602603292/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=7783286046602603292' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/7783286046602603292'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/7783286046602603292'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2009/07/trying-to-get-dual-sim-to-work-in-t.html' title='Trying to get Dual-SIM to work in T-Mobile G1'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_D1ngxQVNLdM/Sla6JNg2d1I/AAAAAAAABgc/FO4iW5FK27I/s72-c/CIMG1878.JPG' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-6849433345859706827</id><published>2009-06-18T17:38:00.000-07:00</published><updated>2011-10-19T11:34:04.013-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Github'/><category scheme='http://www.blogger.com/atom/ns#' term='SSH'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><category scheme='http://www.blogger.com/atom/ns#' term='proxy'/><title type='text'>Using Github Through Draconian Proxies (Windows And Unix)</title><content type='html'>Here is a pretty standard scenario at most corporations:&lt;br /&gt;&lt;br /&gt;- All access to the internet is restricted to a proxy&lt;br /&gt;- The proxy only allows connections out on port 80 and 443&lt;br /&gt;- CONNECT method is only enabled for 443&lt;br /&gt;- Proxy Authentication is required (NTLM or Basic)&lt;br /&gt;&lt;br /&gt;I like to use both Windows and Unix environments. On Unix tunneling to Github is a bit easier because lots of tools are included.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Unix&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;1. Download Git. At the time I was writing this I was using Ubuntu so I simply did apt-get install git-core&lt;br /&gt;&lt;br /&gt;2. Download and install corkscrew (http://www.agroman.net/corkscrew/). This is a tool for tunneling SSH through HTTP proxies.&lt;br /&gt;&lt;br /&gt;3. Edit or create the file ~/.ssh/config and put the following:&lt;br /&gt;&lt;br /&gt;ProxyCommand /usr/bin/corkscrew proxy.example.com 443 %h %p ~/.ssh/myauth&lt;br /&gt;&lt;br /&gt;Host github.com&lt;br /&gt;User git&lt;br /&gt;Port 22&lt;br /&gt;Hostname github.com&lt;br /&gt;IdentityFile "/media/truecrypt1/Keys/GitHubKey.private"&lt;br /&gt;TCPKeepAlive yes&lt;br /&gt;IdentitiesOnly yes&lt;br /&gt;&lt;br /&gt;Host ssh.github.com&lt;br /&gt;User git&lt;br /&gt;Port 443&lt;br /&gt;Hostname ssh.github.com&lt;br /&gt;IdentityFile "/media/truecrypt1/Keys/GitHubKey.private"&lt;br /&gt;TCPKeepAlive yes&lt;br /&gt;IdentitiesOnly yes&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The ProxyCommand is invoked when ssh needs to make a connection. We are telling ssh to use &lt;span style="font-weight: bold;"&gt; /usr/bin/corkscrew&lt;/span&gt;. This is a 3rd party program that sets up a socket through the HTTP proxy.&lt;/li&gt;&lt;li&gt;The program  &lt;span style="font-weight: bold;"&gt; /usr/bin/corkscrew &lt;/span&gt;takes as its 5th argument a file containing credentials for your HTTP proxy. Not all proxies need authentication but if you do just put in the file a single line formatted username:password.&lt;/li&gt;&lt;li&gt;The &lt;span style="font-weight: bold;"&gt;Host github.com&lt;/span&gt; indicates to ssh that if we are connecting to github.com to use these specific settings. There is nothing special here except we specify the location of the private key that corresponds to the public key we had over in http://www.github.com/&lt;/li&gt;&lt;li&gt;Notice we have another entry titled "&lt;span style="font-weight: bold;"&gt;Host ssh.github.com"&lt;/span&gt; . This is to get around proxies that only allow the CONNECT command over 443 (the truly locked down ones). To get around this github setup a whole separate host that listens on port 443. We add both entries here since they are both valid.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;4. If everything is setup correctly you should be able to run:&lt;br /&gt;# ssh github.com&lt;br /&gt;&lt;br /&gt;Hi tachang! You've successfully authenticated, but GitHub does not provide shell access.&lt;br /&gt;Connection to github.com closed.&lt;br /&gt;&lt;br /&gt;If this doesn't work you can run&lt;br /&gt;# ssh ssh.github.com&lt;br /&gt;&lt;br /&gt;And get the exact same thing. If the first command didn't work it means you are using a proxy that blocks CONNECT on port 22. Almost no proxies block CONNECT on port 443 because you need that for SSL.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;We get a no shell access message from github because we are trying to obtain a shell and github has it disabled. However this indicates everything is working. This concludes the setup for Unix.&lt;br /&gt;&lt;br /&gt;------------------------&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Windows&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1. Download msysgit&lt;/span&gt; &lt;a href="http://code.google.com/p/msysgit/"&gt;http://code.google.com/p/msysgit/&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;Some settings:&lt;br /&gt;&lt;br /&gt;- "Run Git from the Windows Command Prompt"&lt;br /&gt;- "Use OpenSSH" (this one is very important)&lt;br /&gt;- Pick your line endings&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. Download connect.c&lt;/span&gt;&lt;br /&gt;&lt;a href="http://bent.latency.net/bent/darcs/goto-san-connect-1.85/src/connect.html"&gt;http://bent.latency.net/bent/darcs/goto-san-connect-1.85/src/connect.html&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;This tool deserves its own post mostly because of its utter simplicity. It mirrors the open source tool corkscrew and is used for tunneling through proxies. Yes the tool's name is really called "connect.c".&lt;br /&gt;&lt;br /&gt;For Window's users, a pre-compiled binary is available:&lt;br /&gt;&lt;a href="http://dl.dropbox.com/u/2177278/connect.exe"&gt;connect.exe&lt;/a&gt;&lt;br /&gt;I put my connect.exe in C:\Windows\connect.exe&lt;br /&gt;&lt;br /&gt;3. Decide whether you like to use the Windows cmd.exe to do stuff or the Cygwin style shell. Or both.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Cygwin Git Bash Shell&lt;/span&gt;&lt;br /&gt;For the Cygwin style shell start up the Git icon and edit the file ~/.ssh/config&lt;br /&gt;*Make sure the file has no extension.&lt;br /&gt;&lt;br /&gt;Put the following in that file:&lt;br /&gt;&lt;br /&gt;ProxyCommand /c/windows/connect.exe -H username@proxy.example.com:443 %h %p&lt;br /&gt;&lt;br /&gt;Host github.com&lt;br /&gt;User git&lt;br /&gt;Port 22&lt;br /&gt;Hostname github.com&lt;br /&gt;IdentityFile "/c/Keys/GitHubKey.private"&lt;br /&gt;TCPKeepAlive yes&lt;br /&gt;IdentitiesOnly yes&lt;br /&gt;&lt;br /&gt;Host ssh.github.com&lt;br /&gt;User git&lt;br /&gt;Port 443&lt;br /&gt;Hostname ssh.github.com&lt;br /&gt;IdentityFile "/c/Keys/GitHubKey.private"&lt;br /&gt;TCPKeepAlive yes&lt;br /&gt;IdentitiesOnly yes&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Notice the slash style in order to access the file system.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The proxy username is specified as part of the proxy setting. The password for the proxy is prompted for. Read more about connect.c to figure out how to get rid of this prompt.&lt;/li&gt;&lt;/ul&gt;At this point, using the Git Bash shell should yield:&lt;br /&gt;&lt;br /&gt;$ ssh github.com&lt;br /&gt;&lt;br /&gt;Hi tachang! You've successfully authenticated, but GitHub does not provide shell access.&lt;br /&gt;Connection to github.com closed&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Windows cmd.exe shell&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Suppose you don't like the Git Bash shell. You prefer the cmd.exe interpreter.&lt;br /&gt;&lt;br /&gt;- Go to your config file at C:\Documents and Settings\&lt;username&gt;\.ssh\config&lt;br /&gt;- Make a copy of it or make a new one. I called mine config-windows&lt;br /&gt;&lt;br /&gt;Put the following in the file:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;ProxyCommand C:/Windows/connect.exe -H username@proxy.example.com:443 %h %p&lt;br /&gt;&lt;br /&gt;Host github.com&lt;br /&gt;User git&lt;br /&gt;Port 22&lt;br /&gt;Hostname github.com&lt;br /&gt;IdentityFile "C:\Keys\GitHubKey.private"&lt;br /&gt;TCPKeepAlive yes&lt;br /&gt;IdentitiesOnly yes&lt;br /&gt;&lt;br /&gt;Host ssh.github.com&lt;br /&gt;User git&lt;br /&gt;Port 443&lt;br /&gt;Hostname ssh.github.com&lt;br /&gt;IdentityFile "C:\Keys\GitHubKey.private"&lt;br /&gt;TCPKeepAlive yes&lt;br /&gt;IdentitiesOnly yes&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Notice the mixture of slash styles. I find this rather odd but it is what works. We have a forward slash style for the ProxyCommand but for the IdentityFile a forward slash or backward slash both work.&lt;/li&gt;&lt;/ul&gt;Running the command (making sure we run Git\bin's ssh.exe and not some other one in the PATH):&lt;br /&gt;&lt;br /&gt;C:\Program Files\Git\bin&gt;ssh.exe -F "C:\Documents and Settings\&lt;username&gt;\.ssh\config-windows" github.com&lt;br /&gt;&lt;br /&gt;Hi tachang! You've successfully authenticated, but GitHub does not provide shell access.&lt;br /&gt;Connection to github.com closed&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;General Git Cloning&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;- Make sure you are using the right Git URL:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Suppose your Public Clone URL is:&lt;a href="git://github.com/zemmekkis/EyeFiServer.git" class="git_url_facebox" rel="#git-clone"&gt; git://github.com/tachang&lt;/a&gt;&lt;a href="git://github.com/zemmekkis/EyeFiServer.git" class="git_url_facebox" rel="#git-clone"&gt;/EyeFiServer.git&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You should use the following URL that utilizes the SSH transport:&lt;br /&gt;&lt;br /&gt;git clone ssh://git@github.com:22/tachang/EyeFiServer.git&lt;br /&gt;git clone ssh://git@ssh.github.com:443/tachang/EyeFiServer.git&lt;/username&gt;&lt;/username&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-6849433345859706827?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/6849433345859706827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=6849433345859706827' title='38 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6849433345859706827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6849433345859706827'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2009/06/using-github-through-draconian-proxies.html' title='Using Github Through Draconian Proxies (Windows And Unix)'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>38</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-324950665629831247</id><published>2009-06-15T17:26:00.000-07:00</published><updated>2009-06-15T17:33:54.567-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Django'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='views.py'/><category scheme='http://www.blogger.com/atom/ns#' term='urls.py'/><title type='text'>Django TypeError Exception</title><content type='html'>One of the central pieces of Django is urls.py:&lt;br /&gt;&lt;br /&gt;http://docs.djangoproject.com/en/dev/topics/http/urls/&lt;br /&gt;&lt;br /&gt;This file is well documented and serves as a central place to match what pages get served by what URLs. Seems simple enough since they accept regular expressions.&lt;br /&gt;&lt;br /&gt;One thing I did run into though was getting a TypeError exception. It looked something like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;TypeError at /applicationname/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;index() takes exactly 1 argument (2 given)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To me I was puzzled why this was happening. The reason is that when Django parses the regular expression it not only does a match but saves each of the tuples in the regular expression. In the documentation it is this line:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;"The view gets passed an HttpRequest as its first argument and any values captured in the regex as remaining arguments."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So what happens is that when you start to get fancy with your regular expressions the function signature in your views.py needs to change as well to accommodate the extra parameters.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-324950665629831247?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/324950665629831247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=324950665629831247' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/324950665629831247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/324950665629831247'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2009/06/django-typeerror-exception.html' title='Django TypeError Exception'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-6641446271501407020</id><published>2009-06-11T10:47:00.000-07:00</published><updated>2011-08-25T12:38:36.477-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SiteMinder'/><title type='text'>SiteMinder R12 Admin GUI</title><content type='html'>If you are upgrading or installing SiteMinder R12 you may have noticed that the traditional admin GUI has changed. The Java applet now asks you for 4 fields.&lt;br /&gt;&lt;br /&gt;Username: This is the username found in the "Administrators" list on the old version 6 GUI. The applet is not case sensitive.&lt;br /&gt;Password: The password in the  "Administrators" list.&lt;br /&gt;Host Name: A 4.x compatible Agent's name&lt;br /&gt;Passphrase: The Shared Secret of the 4.x compatible agent&lt;br /&gt;&lt;br /&gt;The Host Name and Passphrase fields are where things get interesting. SiteMinder R12 is trying heavily to move the functions of this applet to a web based system. The web based system communicates with the SiteMinder policy server using the API. However, the API still uses 4.x agents as the method of authentication to the policy server. 4.x agents have an associated shared secret.&lt;br /&gt;&lt;br /&gt;Thus to get into the traditional 6.0 GUI you need to have a 4.x compatible agent. But what happens when you upgrade to SiteMinder R12 and don't have one? You have two options:&lt;br /&gt;&lt;br /&gt;1. Install the SiteMinder Web Access Manager GUI - Unfortunately the installer for Windows is over 2GB&lt;br /&gt;2. Manually create a 4.x Web Agent&lt;br /&gt;&lt;br /&gt;Option 2 is easiest. We are going to create a file with the proper parameters and then use smobjimport to import it directly to the policy store. To do this create a file called "Generic4xAgent" and put the following in the file:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;objectclass: Agent&lt;br /&gt;Oid: 01-39c83ef9-5c51-4fb4-ba13-193543b8a9d4&lt;br /&gt;Name: siteminder&lt;br /&gt;Desc:&lt;br /&gt;AgentType: 10-8d78bb96-ae15-11d1-9cdd-006008aac24b&lt;br /&gt;RealmHintAttrId: 0&lt;br /&gt;&lt;br /&gt;objectclass: TrustedHost&lt;br /&gt;Oid: 24-5ea55269-d8a9-47a0-864c-c97026c00b99&lt;br /&gt;Name: siteminder&lt;br /&gt;Desc:&lt;br /&gt;IpAddr: 127.0.0.1&lt;br /&gt;Secret: password&lt;br /&gt;Is4xHost: true&lt;br /&gt;RolloverEnabled: false&lt;br /&gt;SecretGenTime: 00000000-00000000-000000000000000000000000000000000000000000000000&lt;br /&gt;SecretUsedTime: 00000000-00000000-000000000000000000000000000000000000000000000000&lt;br /&gt;PrevSecret:&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Save the file as "Generic4xAgent". Now run the command:&lt;br /&gt;smobjimport -iGeneric4xAgent -dsiteminder -wpassword -c&lt;br /&gt;&lt;br /&gt;-i is the filename&lt;br /&gt;-d is the SiteMinder admin username&lt;br /&gt;-w is the SiteMinder admin password&lt;br /&gt;-c indicates that the file has cleartext passwords&lt;br /&gt;&lt;br /&gt;This creates a 4.x agent named "siteminder" with a shared secret of "password".&lt;br /&gt;&lt;br /&gt;At this point you should be able to login to the traditional admin UI.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-6641446271501407020?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/6641446271501407020/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=6641446271501407020' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6641446271501407020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6641446271501407020'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2009/06/siteminder-r12-admin-gui.html' title='SiteMinder R12 Admin GUI'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-5878756243478781852</id><published>2009-05-29T12:18:00.000-07:00</published><updated>2009-05-29T14:05:34.951-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FreeBSD'/><category scheme='http://www.blogger.com/atom/ns#' term='pkg_add'/><title type='text'>Fixing pkg_add -r on FreeBSD (things no one tells you)</title><content type='html'>On FreeBSD when you want to install a program you have to make a choice. Your two choices are to install a package or compile from ports.&lt;br /&gt;&lt;br /&gt;Installing a package means you download a binary package and copy all the files to the right places. Everything is already compiled. This is how Windows works. When you install a piece of software it has already been compiled.&lt;br /&gt;&lt;br /&gt;Your second option is to compile from ports. What this means is that the source files are downloaded and then compiled on your system. You need to have all the prerequisites for the compile to be successful.&lt;br /&gt;&lt;br /&gt;Why choose one over the other? Well with packages sometimes the binary doesn't work. Either you happen to have a newer or older file than what the creator compiled it with or you changed something with your system and it doesn't match anymore with the author's compiled environment. However packages are fast to install. No need to break out gcc and compile source code.&lt;br /&gt;&lt;br /&gt;Ports on the other hand will almost always work. They are targetted for your system because you are compiling them. It takes a bit longer but you also get to customize any of the build options.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;To install a program from package you use this command:&lt;br /&gt;&lt;br /&gt;pkg_add -r &lt;program-name&gt;&lt;br /&gt;&lt;br /&gt;Examples:&lt;br /&gt;&lt;br /&gt;pkg_add -r xorg&lt;br /&gt;pkg_add -r nano&lt;br /&gt;pkg_add -r curl&lt;br /&gt;&lt;br /&gt;I like pkg_add -r because it fetches the package for me and installs it. It does that by looking at your system's uname (I think) and forms a URL to FreeBSD's software repository. The problem is that after a while repositories are taken offline. So if you are using some older version of FreeBSD and trying to do a pkg_add -r it will return that it can't find the package.&lt;br /&gt;&lt;br /&gt;The thing is, the package is probably still around but in a newer form. The newer package is compatible with your version if you can find it. FreeBSD makes a statement that says packages in the same stable branch will always be compatible.&lt;br /&gt;&lt;br /&gt;To force pkg_add -r to bend to your will you edit the &lt;tt class="ENVAR"&gt;PACKAGESITE&lt;span style="font-family:Georgia,serif;"&gt; &lt;/span&gt;&lt;/tt&gt;environment variable. If you want to force pkg_add -to download FreeBSD 7-STABLE packages, set &lt;tt class="ENVAR"&gt;PACKAGESITE&lt;/tt&gt; to &lt;tt class="LITERAL"&gt;ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/packages-7-stable/Latest/&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;Be very careful though that you point to the right URL. I actually pointed to the wrong URL and downloaded 32-bit packages instead of the amd64 packages which I needed:&lt;br /&gt;&lt;br /&gt;http://ftp2.at.freebsd.org/pub/FreeBSD/ports/amd64/packages-7-stable/Latest/&lt;br /&gt;&lt;br /&gt;&lt;tt class="ENVAR"&gt;&lt;/tt&gt;&lt;/program-name&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-5878756243478781852?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/5878756243478781852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=5878756243478781852' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/5878756243478781852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/5878756243478781852'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2009/05/fixing-pkgadd-r-on-freebsd-things-no.html' title='Fixing pkg_add -r on FreeBSD (things no one tells you)'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-2329337696017668293</id><published>2009-05-12T12:14:00.001-07:00</published><updated>2009-05-12T12:22:43.250-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bluetooth'/><category scheme='http://www.blogger.com/atom/ns#' term='obex'/><category scheme='http://www.blogger.com/atom/ns#' term='file transfer'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Ubuntu: Getting files off your phone using bluetooth</title><content type='html'>Sometimes you just want to get a file off your phone. One of the easiest ways to do this is bluetooth. The problem is that some carriers (such as Verizon) lock their phones down so you can't transfer files from your phone to your PC over bluetooth.&lt;br /&gt;&lt;br /&gt;The real technicality is that while the phone can't initiate the sending of the file, you can still browse the phone for files and pull them.&lt;br /&gt;&lt;br /&gt;So far the most useful tool I found to get files off my phone (which is an LG Chocolate) is obexftp.&lt;br /&gt;&lt;br /&gt;To get started install the package using Synaptic then open up a console and type:&lt;br /&gt;&lt;br /&gt;$ obexftp -b&lt;br /&gt;&lt;br /&gt;When you find a device you want you connect to it like so:&lt;br /&gt;&lt;br /&gt;$ obexftp -b 00:1E:75:ED:62:2C -l&lt;br /&gt;Browsing 00:1E:75:ED:62:2C ...&lt;br /&gt;Channel: 7&lt;br /&gt;Connecting...done&lt;br /&gt;Receiving "(null)"...&lt;br /&gt;&lt;folder-listing version="1.0"&gt;&lt;folder name="MySounds"&gt;&lt;folder name="MyPictures"&gt;&lt;folder name="MyVideos"&gt;&lt;folder name="SdPictures"&gt;&lt;folder name="SdSounds"&gt;done&lt;br /&gt;Disconnecting...done&lt;br /&gt;&lt;br /&gt;The way obexftp works is that you basically have to run the command over and over with different options to get what you want. So after running it with this "list" option I say I want to browse the folder "MyPictures".&lt;br /&gt;&lt;br /&gt;$ obexftp -b 00:1E:75:ED:62:2C -c MyPictures -l&lt;br /&gt;Browsing 00:1E:75:ED:62:2C ...&lt;br /&gt;Channel: 7&lt;br /&gt;Connecting...done&lt;br /&gt;Sending "MyPictures"... done&lt;br /&gt;Receiving "(null)"...&lt;br /&gt;&lt;folder-listing version="1.0"&gt;&lt;parent-folder&gt;&lt;file name="0309091806.jpg" size="210900"&gt;done&lt;br /&gt;Disconnecting...done&lt;br /&gt;&lt;br /&gt;Now that I know the location of the file I can procede to actually get the file.&lt;br /&gt;&lt;br /&gt;$ obexftp -b 00:1E:75:ED:62:2C -c MyPictures -g 0512091207.jpg&lt;br /&gt;Browsing 00:1E:75:ED:62:2C ...&lt;br /&gt;Channel: 7&lt;br /&gt;Connecting...done&lt;br /&gt;Sending "MyPictures"... done&lt;br /&gt;Receiving "0512091207.jpg"...|done&lt;br /&gt;Disconnecting...done&lt;br /&gt;&lt;br /&gt;Easy enough. Probably not the most intuitive way to do things but it gets the job done.&lt;/file&gt;&lt;/parent-folder&gt;&lt;/folder-listing&gt;&lt;/folder&gt;&lt;/folder&gt;&lt;/folder&gt;&lt;/folder&gt;&lt;/folder&gt;&lt;/folder-listing&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-2329337696017668293?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/2329337696017668293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=2329337696017668293' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/2329337696017668293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/2329337696017668293'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2009/05/ubuntu-getting-files-off-your-phone.html' title='Ubuntu: Getting files off your phone using bluetooth'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-6436888483369683537</id><published>2009-04-27T15:57:00.000-07:00</published><updated>2009-04-27T16:08:12.383-07:00</updated><title type='text'>Obtaining a Free Fully Trusted SSL Certificate</title><content type='html'>Ever get that popup when you visited a supposedly "secure" website that says the certificate is not trusted? Reason you get that popup is because the person who signed/issued the certificate is not trusted by default on your computer.&lt;br /&gt;&lt;br /&gt;The business of selling certificates is a lucrative one. Large certificate authorities such as Thawte and VeriSign make a killing issuing digital certifcates. They can arbitrarily adjust the parameters on the certificate and charge for it on a case by case basis. The reason they are able to do so is because almost every computer by default trusts these companies. You can check this in Windows by going to start, run, mmc.exe and adding the Certificate snap in. Look under Trusted Root Certification Authorities.&lt;br /&gt;&lt;br /&gt;In general you have to pay quite a bit of money to get a certificate signed by one of these authorities. However there is one way to get a virtually "free" one.&lt;br /&gt;&lt;br /&gt;Thawte offers a program called their Web of Trust:&lt;br /&gt;&lt;br /&gt;&lt;a href="https://www.thawte.com/cgi/personal/wot/contents.exe"&gt;https://www.thawte.com/cgi/personal/wot/contents.exe&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;Basically after going through the steps Thawte will give you a free certificate signed by an authority called "Thawte Personal Freemail CA". Because this CA is installed by default on all Windows installations it is trusted everywhere.&lt;br /&gt;&lt;br /&gt;Getting this certificate involves a combination of sending in documents to Thawte or finding people who have already gone through the process to vouch for you. Once you have it though you keep it forever (as far as I can see) and can generate certificates with your e-mail address in it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-6436888483369683537?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/6436888483369683537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=6436888483369683537' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6436888483369683537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6436888483369683537'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2009/04/obtaining-free-fully-trusted-ssl.html' title='Obtaining a Free Fully Trusted SSL Certificate'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-4810300617290155729</id><published>2009-04-15T14:35:00.000-07:00</published><updated>2009-04-15T15:07:34.270-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xmlsec'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='pyxmlsec'/><title type='text'>PyXMLSec Windows Binary</title><content type='html'>&lt;h1  style="font-weight: bold;font-family:arial;"&gt;&lt;span style="font-size:100%;"&gt;Xmlsec Python Bindings for Windows&lt;/span&gt;&lt;/h1&gt; Getting the python xmlsec library to work on windows is a bit of work though it really shouldn't be. Provided here are windows installers for xmlsec. The installer itself is produced by python distutils.&lt;br /&gt;&lt;br /&gt;In order to get it to work you will also need libxml2. I am providing a copy of it here as well.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.darkeneddesire.com/blogger/python/pyxmlsec-0.3.0.win32-py2.6.exe"&gt;pyxmlsec-0.3.0.win32-py2.6.exe&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.darkeneddesire.com/blogger/python/libxml2-python-2.7.3.win32-py2.6.exe"&gt;libxml2-python-2.7.3.win32-py2.6.exe&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I used MinGW for compilation. The entire environment I used to compile pyxmlsec is available here. Look inside the pyxmlsec directory for build.bat.&lt;br /&gt;&lt;a href="PythonWindowsCompileEnvironment.zip"&gt;PythonWindowsCompileEnvironment.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-4810300617290155729?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/4810300617290155729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=4810300617290155729' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/4810300617290155729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/4810300617290155729'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2009/04/pyxmlsec-windows-binary.html' title='PyXMLSec Windows Binary'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-6478252334706825910</id><published>2009-04-02T19:56:00.000-07:00</published><updated>2010-01-07T21:11:01.105-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='server'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='EyeFi'/><category scheme='http://www.blogger.com/atom/ns#' term='standalone'/><category scheme='http://www.blogger.com/atom/ns#' term='Eye-Fi'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Eye Fi Standalone Server Version 2.0</title><content type='html'>I'd like to release an updated version of the Eye Fi standalone server in python that I have been working on. This version should work on Linux, Mac OS X, Windows, Solaris, or wherever else you can load a Python interpreter. As always I love comments so if you are using this feel free to e-mail me or drop me a note!&lt;br /&gt;&lt;br /&gt;Source on GitHub: &lt;a href="http://github.com/tachang/EyeFiServer"&gt;http://github.com/tachang/EyeFiServer&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Download (zip)&lt;/span&gt;: &lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;a href="http://www.darkeneddesire.com/EyeFiServer/2.0/EyeFiServer-v2.0.zip"&gt;http://www.darkeneddesire.com/EyeFiServer/2.0/EyeFiServer-v2.0.zip&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;I know some people just like to browse around the source without having to download stuff (I'm one of those people):&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.darkeneddesire.com/EyeFiServer/2.0/Release/"&gt;http://www.darkeneddesire.com/EyeFiServer/2.0/Release/&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;This new version has the following features:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The server can now execute an arbitrary command on each uploaded photo. This is a very dangerous feature and should be used with caution. On the other hand it is also very cool. You can have the server FTP files, display them using an image viewer, or even run sorting programs on the images.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Improved security: the server now generates its own nonces instead of using one that was hard coded. The nonce is based on the random library provided by python. The INTEGRITYDIGEST field is also checked.&lt;/li&gt;&lt;li&gt;Ability to read settings from a configuration file (there is a included DefaultSettings.ini for reference). The file allows you to configure the listen port, console output, logging, download location, and execute on upload, and upload key.&lt;/li&gt;&lt;/ul&gt;Some other notable improvements but not really features are the addition of regression tests and support for Python 2.5.  The regression tests are interesting since I run them against the official Eye-Fi Manager to make sure my behavior is a close match.&lt;br /&gt;&lt;br /&gt;Getting usage information as to how to specify a configuration file:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;C:\EyeFiServer\Release&gt;EyeFiServer.py -h&lt;/span&gt;&lt;br /&gt;Usage: EyeFiServer.py [options]&lt;br /&gt;&lt;br /&gt;Options:&lt;br /&gt; -h, --help            show this help message and exit&lt;br /&gt; -c CONFIGFILE, --config=CONFIGFILE&lt;br /&gt;                       Path to configuration file (example in&lt;br /&gt;                       DefaultSettings.ini)&lt;br /&gt;&lt;br /&gt;Actually specifying a configuration file:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;C:\EyeFiServer\Release&gt;EyeFiServer.py -c DebugSettings.ini&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-6478252334706825910?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/6478252334706825910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=6478252334706825910' title='188 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6478252334706825910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6478252334706825910'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2009/04/eye-fi-standalone-server-version-20.html' title='Eye Fi Standalone Server Version 2.0'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>188</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-1937325780893140153</id><published>2009-01-27T15:33:00.001-08:00</published><updated>2011-10-31T09:59:38.940-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='LDAP'/><category scheme='http://www.blogger.com/atom/ns#' term='CSV'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='Converting LDIF to CSV'/><category scheme='http://www.blogger.com/atom/ns#' term='LDIF to CSV'/><category scheme='http://www.blogger.com/atom/ns#' term='LDIF'/><title type='text'>Converting LDIF/LDAP data into a CSV file</title><content type='html'>&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;LDIF to CSV&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I work with LDAP on a regularly basis. I frequently have to pull data using ldapsearch. While the data that ldapsearch spits out is a decent representation sometimes I want something a bit easier to work with.&lt;br /&gt;&lt;br /&gt;The format I use most tends to be CSV. While the acronym stands for comma separated value the format may be used to describe data that is printed out line by line and separated by anything you can imagine.&lt;br /&gt;&lt;br /&gt;The problem for me is finding a decent LDIF to CSV converter. The ones that I have tried tend to choke on any number of issues. Some of these include binary data or failing to normalize the multivalued attributes.&lt;br /&gt;&lt;br /&gt;I finally got sick enough of these issues that I decided to write my own. You can download it here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://dl.dropbox.com/u/2177278/LDIFtoCSV-src-v1.0.zip"&gt;Python/Linux/Source&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://dl.dropbox.com/u/2177278/LDIFtoCSV-win32-v1.0.zip"&gt;Windows&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Hopefully the Windows binary works for you. If it doesn't then just download Python 2.6 and run the source manually. I am providing the binary just for convenience.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-size:130%;"&gt;Using LDIFtoCSV&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Running "python LDIFtoCSV.py" should give you the usage text.&lt;br /&gt;&lt;br /&gt;usage: LDIFtoCSV.py [options] &lt;ldif_file&gt;&lt;br /&gt;&lt;br /&gt;-o &amp;lt;filename&amp;gt;   : File to write output. By default this is set to sys.stdout&lt;br /&gt;-l &amp;lt;filename&amp;gt;   : File to write logging output. By default there is no logging.&lt;br /&gt;-F &amp;lt;char&amp;gt;       : Character to separate the fields by. By default this is a comma. i.e. -F","&lt;br /&gt;-D &amp;lt;char&amp;gt;       : Character to delimit the text value by. By default this is a double quote. i.e. -D"""&lt;br /&gt;-M &amp;lt;num&amp;gt;        : The maximum number of columns a multivalued attribute should take up (default: 5). This is common with the objectClass attribute where it can have over 20 values. Do you want to have 20 columns each with the same heading objectClass or do you want to limit it.&lt;br /&gt;&lt;br /&gt;Here are some common command lines that I use (assuming you have a test.ldif):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Outputs the CSV straight to standard output:&lt;/span&gt;&lt;br /&gt;python LDIFtoCSV.py test.ldif&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Outputs CSV to standard output with semicolons as the delimiter:&lt;/span&gt;&lt;br /&gt;&lt;/ldif_file&gt;python LDIFtoCSV.py -F";" test.ldif&lt;ldif_file&gt;&lt;br /&gt;&lt;br /&gt;&lt;/ldif_file&gt;&lt;span style="font-weight: bold;"&gt;Outputs CSV to standard output with pipes as the delimiter and text surrounded by carrots:&lt;/span&gt;&lt;br /&gt;python LDIFtoCSV.py -F"|" -D"^" test.ldif&lt;br /&gt;&lt;ldif_file&gt;&lt;br /&gt;&lt;br /&gt;&lt;/ldif_file&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-1937325780893140153?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/1937325780893140153/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=1937325780893140153' title='28 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/1937325780893140153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/1937325780893140153'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2009/01/converting-ldifldap-data-into-csv-file.html' title='Converting LDIF/LDAP data into a CSV file'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>28</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-5987368060820209870</id><published>2009-01-21T13:24:00.000-08:00</published><updated>2009-01-27T15:32:50.819-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='LDAP'/><category scheme='http://www.blogger.com/atom/ns#' term='Outlook'/><category scheme='http://www.blogger.com/atom/ns#' term='GAL'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='LDIF'/><category scheme='http://www.blogger.com/atom/ns#' term='Active Directory'/><title type='text'>Downloading the Global Address List from Outlook/Exchange</title><content type='html'>&lt;span style="font-weight: bold;font-size:130%;" &gt;Getting the Data&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Recently I had a need to dump the entire Global Address List from within Outlook. Usually the address list will contain the contact information for your entire organization.&lt;br /&gt;&lt;br /&gt;The most effective way I have found to do this is a straight LDAP search on the Active Directory and pull everything into an LDIF file. Conceptually it is straightforward but I have found the most difficult part is usually trying to get all the pieces together. So subscribing to the French idea of "mise en place" here is what you'll need:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Username&lt;/span&gt;&lt;br /&gt;Your username is your fully qualified distinguished name. It is not your Windows login name. It commonly looks something like "CN=Tchang\, Jeff,OU=Users,OU=USA,DC=example,DC=com".&lt;br /&gt;&lt;br /&gt;The easiest way I have found to obtain your username is to login to a Windows machine and then put the following two lines in a text file with the extension .vbs:&lt;br /&gt;&lt;br /&gt;Set objADSysInfo = WScript.CreateObject("ADSystemInfo")&lt;br /&gt;result = InputBox("Active Directory Username (copy and paste as necessary)", "Active Directory Username", objADSysInfo.UserName, 100, 100)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Password&lt;/span&gt;&lt;br /&gt;The password will be your domain password.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Domain controller hostname&lt;/span&gt;&lt;br /&gt;Couple of ways to get this. This will be the Active Directory/LDAP server that you will extract the entries. An echo %logonserver% at the command prompt usually works.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Ldapsearch tool&lt;/span&gt;&lt;br /&gt;Easiest way to get the tools is from Sun's iPlanet Directory SDK. Go to &lt;a href="http://www.sun.com/download/products.xml?id=3ec28dbd"&gt;http://www.sun.com/download/products.xml?id=3ec28dbd&lt;/a&gt; and select the iPlanet Directory SDK downloads. After download the zipfile find the executable named ldapsearch.exe.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Performing the search&lt;/span&gt;&lt;br /&gt;Here is an example syntax to extract out all the users:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Windows:&lt;/span&gt;&lt;br /&gt;ldapsearch.exe -b OU=Users,OU=USA,DC=example,DC=com -h host.example.com -p 389 -D "CN=Tchang\, Jeff,OU=Users,OU=USA,DC=example,DC=com" -w - (objectClass=*)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Unix:&lt;/span&gt;&lt;br /&gt;ldapsearch -b OU=Users,OU=USA,DC=example,DC=com -h host.example.com -p 389 -D "CN=Tchang\, Jeff,OU=Users,OU=USA,DC=example,DC=com" -W -x "(objectClass=*)"&lt;br /&gt;&lt;br /&gt;The -b is for the base. In this example I knew the users were all stored in that branch. -D is for username. -w - (that is a dash w followed by a dash) means to read the password from the console. On Unix the big -W is to prompt and the -x indicates you want simple authentication (cleartext username/password).&lt;br /&gt;&lt;br /&gt;You might want to add a " &gt; output.txt" to send the output to a file. If you do that you will have to supply the password on the command line.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-5987368060820209870?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/5987368060820209870/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=5987368060820209870' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/5987368060820209870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/5987368060820209870'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2009/01/downloading-global-address-list-from.html' title='Downloading the Global Address List from Outlook/Exchange'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-6641396281051079889</id><published>2009-01-04T12:04:00.000-08:00</published><updated>2009-04-04T16:21:40.460-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='server'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='EyeFi'/><category scheme='http://www.blogger.com/atom/ns#' term='standalone'/><category scheme='http://www.blogger.com/atom/ns#' term='Eye-Fi'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><title type='text'>Eye Fi Standalone Server</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Eye Fi Linux Hacking&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So I spent some time over my vacation learning a bit more about Python. What better way to learn a language than to implement something you want or need, right?&lt;br /&gt;&lt;br /&gt;I am releasing a standalone Eye-Fi server written in Python.  Basically I saw Dave Hansen's post (&lt;a href="http://dave-hansen.blogspot.com/2008/12/freestanding-server.html"&gt;http://dave-hansen.blogspot.com/2008/12/freestanding-server.html&lt;/a&gt;) and went ahead and did it. This software works on Windows with Python 2.6. I have not tested it on Linux/Unix yet but I assume it will work seeing as how it is written in Python. Please let me know if you try this software out and it works or doesn't. I personally would love any comments!&lt;br /&gt;&lt;br /&gt;Python script is here: &lt;a href="http://www.darkeneddesire.com/EyeFiServer/EyeFiServer.py"&gt;http://www.darkeneddesire.com/EyeFiServer/EyeFiServer.py&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;General Architecture Notes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is a standalone Eye-Fi Server that is designed to take the place of the Eye-Fi Manager.&lt;br /&gt;&lt;br /&gt;Starting this server creates a listener on port 59278. I use the BaseHTTPServer class included with Python. I look for specific POST/GET request URLs and execute functions based on those&lt;br /&gt;URLs.&lt;br /&gt;&lt;br /&gt;Currently all files are downloaded to the directory in which this script is run.&lt;br /&gt;&lt;br /&gt;To use this script you need to have your Eye-Fi upload key.&lt;br /&gt;It is in C:\Documents and Settings\[User]&lt;user&gt;\Application Data\Eye-Fi\Settings.xml&lt;br /&gt;&lt;br /&gt;Simple search for "eyeFiUploadKey" and replace it with your key.&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;br /&gt;Update (4/4/09) - &lt;a href="http://returnbooleantrue.blogspot.com/2009/04/eye-fi-standalone-server-version-20.html"&gt;http://returnbooleantrue.blogspot.com/2009/04/eye-fi-standalone-server-version-20.html&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/user&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-6641396281051079889?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/6641396281051079889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=6641396281051079889' title='95 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6641396281051079889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6641396281051079889'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2009/01/eye-fi-standalone-server.html' title='Eye Fi Standalone Server'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>95</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-3320291692663959766</id><published>2008-12-25T18:06:00.000-08:00</published><updated>2008-12-25T18:20:32.081-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tcp'/><category scheme='http://www.blogger.com/atom/ns#' term='BaseHTTPServer'/><category scheme='http://www.blogger.com/atom/ns#' term='EyeFi'/><category scheme='http://www.blogger.com/atom/ns#' term='Eye-Fi'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='timeouts'/><title type='text'>Troubleshooting Python's BaseHTTPServer</title><content type='html'>Everytime I run into some really weird issue I tend to like to write about it if only because it will help me remember it if I ever encounter it at a later date.&lt;br /&gt;&lt;br /&gt;One the things I am working on is a standalone Eye-Fi server that receives HTTP SOAP requests from a small wireless device. My previous attempts at implementing one have been mostly successful: I used Apache and PHP to hack something quick together.&lt;br /&gt;&lt;br /&gt;Looking back at the code I decided to try my hand at Python and implementing a simple web server. I looked up a tutorial on BaseHTTPServer and went on my merry way. The server worked pretty well when I loaded it through a web browser (IE/Firefox) but seemed to hang when the Eye-Fi card contacted it.&lt;br /&gt;&lt;br /&gt;The error was rather interesting in that Python exceptioned indicating the remote host forcibly closed the connection. I was pretty lost as to why that was.&lt;br /&gt;&lt;br /&gt;At first I thought it was something wrong with how the BaseHTTPServer was written. So I went looking around the source trying to find anything about TCP timeouts or how to disable them. I eventually broke down and ran WireShark. This showed me that the request was infact getting through to the web server but never making it up to the POST/GET handlers. So I started looking at buffers and how python knows to finish a line. It turns out that there is a bug in the Eye-Fi card. One of the requests it makes does not end with a carriage return or line feed. This causes the server to block on input. Eventually the TCP connection times out and resets are sent.&lt;br /&gt;&lt;br /&gt;The solution was simply to upgrade to a later version of the firmware. Firmware 2.0001 seems to work well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-3320291692663959766?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/3320291692663959766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=3320291692663959766' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/3320291692663959766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/3320291692663959766'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2008/12/troubleshooting-pythons-basehttpserver.html' title='Troubleshooting Python&apos;s BaseHTTPServer'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-4558931688076713253</id><published>2008-12-25T13:36:00.000-08:00</published><updated>2008-12-25T13:48:38.617-08:00</updated><title type='text'>Manually authenticating to a proxy server with netcat or telnet</title><content type='html'>Sometimes when testing a web application you want to have total control of what you are sending to the web server. However, sometimes that web application is behind an authenticating proxy. This setup is pretty common in large enterprises.&lt;br /&gt;&lt;br /&gt;Authentication is basically accomplished with an HTTP header called "Proxy-Authorization". The header's value is typically a username/password pair that is Base64 encoded.&lt;br /&gt;&lt;br /&gt;Suppose your username is "Thomas" and your password is "crown". To form the header's value you would concatenate the username, a colon, and the password in one big string. This would turn out as:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Thomas:crown&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You would then Base64 encode this value:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;VGhvbWFzOmNyb3du&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The final header that you would type in a netcat or telnet session would be:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Proxy-Authorization: Basic VGhvbWFzOmNyb3du&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A full example of this in use:&lt;br /&gt;&lt;br /&gt;telnet proxy.example.com 80&lt;br /&gt;CONNECT somewebsite.example.com:80 HTTP/1.1&lt;br /&gt;Proxy-Authorization: Basic VGhvbWFzOmNyb3du&lt;br /&gt;&lt;br /&gt;GET / HTTP/1.1&lt;br /&gt;&lt;br /&gt;Also don't forget to watch the carriage returns. The RFC concerning Proxy-Authorization can be found here: &lt;a href="http://www.freesoft.org/CIE/RFC/2068/195.htm"&gt;http://www.freesoft.org/CIE/RFC/2068/195.htm&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-4558931688076713253?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/4558931688076713253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=4558931688076713253' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/4558931688076713253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/4558931688076713253'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2008/12/manually-authenticating-to-proxy-server.html' title='Manually authenticating to a proxy server with netcat or telnet'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-6388798506174702088</id><published>2008-12-11T16:28:00.001-08:00</published><updated>2008-12-11T16:29:00.773-08:00</updated><title type='text'>How to determine if a file is 32 or 64 bit on AIX</title><content type='html'>I was working on an AIX box recently and had to figure out if a binary was 32 or 64 bit. Took me a bit since I am not that familiar with AIX but I eventually figured out two methods:&lt;br /&gt;&lt;br /&gt;The first is using the 'file' command. For a 32-bit binary this command produced the following output:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;# file libmod_sm20.so&lt;/span&gt;&lt;br /&gt;libmod_sm20.so: executable (RISC System/6000) or object module&lt;br /&gt;&lt;br /&gt;However on a 64-bit binary it actually stated 64 bits:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;# file libmod_sm20.so&lt;/span&gt;&lt;br /&gt;libmod_sm20.so: 64-bit XCOFF executable or object module not stripped&lt;br /&gt;&lt;br /&gt;The other way was to use the 'nm' command. Not entirely sure what nm stands for. Perhaps name mangling or just 'name'.&lt;br /&gt;&lt;br /&gt;In any case this command has the '-X' switch which allows you to specify the type of file. So if you wanted to examine only 32 bit object files you would use '-X 32'. For 64-bit you would use '-X 64'. And for both you would use '-X32-64'.&lt;br /&gt;&lt;br /&gt;Running nm with the 32-bit flag:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;# nm -X32 libmod_sm20.so&lt;/span&gt;&lt;br /&gt;0654-210 libmod_sm20.so is not valid in the current object file mode.&lt;br /&gt;        Use the -X option to specify the desired object mode.&lt;br /&gt;&lt;br /&gt;Basically gives me an error. However&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;# nm -X64 libmod_sm20.so&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;will produce copious amounts of output. This means that libmod_sm20.so is a 64-bit file because the libraries it is linking to are 64-bit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-6388798506174702088?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/6388798506174702088/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=6388798506174702088' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6388798506174702088'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/6388798506174702088'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2008/12/how-to-determine-if-file-is-32-or-64.html' title='How to determine if a file is 32 or 64 bit on AIX'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-7353563915880546216</id><published>2008-12-08T15:44:00.000-08:00</published><updated>2008-12-08T15:48:56.340-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='curl'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='libcurl'/><title type='text'>Tutorial for cURL, libcurl, and Python</title><content type='html'>When troubleshooting websites it often comes down to what tools you know and if you know how to use them. One of the most valuable tools in my internet troubleshooting toolkit is cURL. I usually use curl to emulate a web browser. It gives me fine grained control over all the traffic that is being sent to the webserver.&lt;br /&gt;&lt;br /&gt;cURL (or curl) usually refers to a binary based on libcurl. The binary is basically a very well designed swiss army knife for working with HTTP type connections. It supports other types of connections but for someone just learning curl the most useful is its HTTP capabilities.&lt;br /&gt;&lt;br /&gt;The other extremely useful thing about curl is libcurl. The actual library allows you to script a lot of HTTP processes. The language you use to script really depends if there exists a binding for libcurl in your language. While libcurl is written in C it doesn't mean you need to use that language.&lt;br /&gt;&lt;br /&gt;Libcurl is available in a number of languages from this website: http://curl.haxx.se/libcurl/bindings.html&lt;br /&gt;&lt;br /&gt;So far I've used the bindings in PHP, Java, Perl, and Python. So basically pick the language you are most familiar with and go from there. The best way to learn a new tool is by example.&lt;br /&gt;&lt;br /&gt;The following is a code snippet for Python that posts to http://www.google.com/.&lt;br /&gt;&lt;br /&gt;import pycurl&lt;br /&gt;import StringIO&lt;br /&gt;&lt;br /&gt;proxyHostAndPort = 'localhost:8888'&lt;br /&gt;proxyAuthentication = 'username:password'&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;buffer = StringIO.StringIO()&lt;br /&gt;&lt;br /&gt;c = pycurl.Curl()&lt;br /&gt;c.setopt(c.URL, 'http://www.google.com/')&lt;br /&gt;c.setopt(c.COOKIEJAR, 'cookies.txt')&lt;br /&gt;c.setopt(c.COOKIEFILE, 'cookies.txt')&lt;br /&gt;&lt;br /&gt;c.setopt(c.POST, 1)&lt;br /&gt;c.setopt(c.POSTFIELDS, "User=smith&amp;amp;Password=password")&lt;br /&gt;c.setopt(c.VERBOSE, 1)&lt;br /&gt;c.setopt(c.REFERER,'')&lt;br /&gt;c.setopt(c.USERAGENT,'Curl')&lt;br /&gt;c.setopt(c.WRITEFUNCTION, buffer.write)&lt;br /&gt;c.setopt(c.SSL_VERIFYHOST, 0)&lt;br /&gt;c.setopt(c.SSL_VERIFYPEER, False)&lt;br /&gt;&lt;br /&gt;c.setopt(c.PROXY, proxyHostAndPort)&lt;br /&gt;c.setopt(c.PROXYUSERPWD, proxyAuthentication)&lt;br /&gt;&lt;br /&gt;c.perform()&lt;br /&gt;c.close()&lt;br /&gt;&lt;br /&gt;print buffer.getvalue()&lt;blockquote&gt;&lt;/blockquote&gt;&lt;br /&gt;Not that useful but the main things you want to glean from the code are the use of cookies, the POST method, an authenticating proxy, and results in the form of a string. Curl can also set the referrer and useragent headers to arbitrary values. This whole package is what makes curl so powerful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-7353563915880546216?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/7353563915880546216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=7353563915880546216' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/7353563915880546216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/7353563915880546216'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2008/12/tutorial-for-curl-libcurl-and-python.html' title='Tutorial for cURL, libcurl, and Python'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2044427065375438750.post-316706374360955026</id><published>2008-11-12T13:35:00.000-08:00</published><updated>2009-04-15T15:16:21.604-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xmlsec'/><category scheme='http://www.blogger.com/atom/ns#' term='libxml'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><category scheme='http://www.blogger.com/atom/ns#' term='pyxmlsec'/><category scheme='http://www.blogger.com/atom/ns#' term='compiling'/><title type='text'>Compiling PyXMLSec for Windows</title><content type='html'>For some reason there doesn't seem to be anyone that compiled PyXMLSec for Windows. Not sure why but I tried searching for all sorts of terms and nada. So I went on a bit of an adventure to get this thing working. Fair warning: while this works for the most part I mixed and matched a few of the binary packages without really researching the platform they were compiled on and whether they really would be compatible.&lt;br /&gt;&lt;br /&gt;If you are looking to just download the binary go here:&lt;br /&gt;&lt;a href="http://returnbooleantrue.blogspot.com/2009/04/pyxmlsec-windows-binary.html"&gt;http://returnbooleantrue.blogspot.com/2009/04/pyxmlsec-windows-binary.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;List of everything I used:&lt;br /&gt;&lt;br /&gt;- MinGW. I used version 5.1.4.&lt;br /&gt;- PyXMLSec source code. For this I used pyxmlsec-0.3.0.&lt;br /&gt;- libxml2-2.5.10.win32&lt;br /&gt;- iconv-1.9.2.win32&lt;br /&gt;- libxmlsec-1.2.11.win32&lt;br /&gt;- libxslt-1.1.24.win32&lt;br /&gt;- zlib-1.2.3.win32&lt;br /&gt;- Win32OpenSSL-0_9_8i.exe and Microsoft Visual C++ 2008 Redistributable Package (x86) from the same site&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;First thing I did was look at the setup.py script included inside  pyxmlsec.&lt;br /&gt;&lt;br /&gt;A bit down in the file is a list of all the files that need to be compiled.&lt;br /&gt;&lt;br /&gt;sources = ["utils.c", "wrap_objs.c",&lt;br /&gt;        "app.c", "base64.c", "buffer.c", "errors.c",&lt;br /&gt;        "keyinfo.c", "keys.c", "keysdata.c", "keysmngr.c",&lt;br /&gt;        "list.c", "membuf.c", "nodeset.c", "parser.c",&lt;br /&gt;        "templates.c", "transforms.c", "version.c",&lt;br /&gt;        "xmldsig.c", "xmlenc.c", "xmlsec.c", "xmltree.c",&lt;br /&gt;        "x509.c",&lt;br /&gt;        "xmlsecmod.c"]&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Looked pretty straghtforward to me. Took out my compiler and proceded to start:&lt;br /&gt;&lt;br /&gt;&gt; gcc *.c&lt;br /&gt;&lt;br /&gt;One can hope right? Obviously all this does is spew out a ridiculous number of errors and warnings. So I set about troubleshooting them one by  one. I decide to just pick a single .c file to just get a small number of warnings. I was too lazy to pipe output to a file.&lt;br /&gt;&lt;br /&gt;&gt; gcc utils.c&lt;br /&gt;&lt;br /&gt;In file included from utils.c:27:&lt;br /&gt;utils.h:5:20: Python.h: No such file or directory&lt;br /&gt;&lt;br /&gt;well this is simple enough to fix. utils.c is expecting the Python.h header file. So lets give the compiling the path to the headers using the  -I option.&lt;br /&gt;&lt;br /&gt;&gt; gcc -IC:\Python25\include utils.c&lt;br /&gt;&lt;br /&gt;utils.c:(.text+0x4f): undefined reference to `_imp__PyInstance_Type'&lt;br /&gt;&lt;br /&gt;So these turn out to be linking errors. So let us link to the Python libraries. We need to include the -lpython25 to explicitly tell gcc that the library we want is python25.&lt;br /&gt;&lt;br /&gt;&gt; gcc -IC:\Python25\include -LC:\Python25\libs utils.c -lpython25&lt;br /&gt;&lt;br /&gt;utils.c:(.text+0x8e): undefined reference to `xmlsec_error'&lt;br /&gt;&lt;br /&gt;So now I get errors about linking to the xmlsec library. Well this makes sense since I didn't tell gcc where the xmlsec libraries were. PyXMLSec depends on xmlsec.&lt;br /&gt;&lt;br /&gt;At this point I am dreading I will have to compile xmlsec for windows as well. Luckily windows binaries for the XMLSec Library (as well as LibXML2, LibXSLT and OpenSSL) are available from Igor Zlatkovic. I will make a big caveat here though. Some of the binaries that I got from Igor did not work for me. One of the errors was about newline characters being missing in his openssl binary package. To solve this I downloaded&lt;br /&gt;&lt;br /&gt;Win32 OpenSSL v0.9.8i from Shining Light Productions (http://www.slproweb.com/products/Win32OpenSSL.html) and linked against that.&lt;br /&gt;&lt;br /&gt;The other issue was with libxml2. Don't try to use the newest version or else you will run into issues.&lt;br /&gt;&lt;br /&gt;Now here is the relatively time consuming part. Need to unpack them all and make sure gcc knows about the locations.&lt;br /&gt;&lt;br /&gt;This is what we have so far.&lt;br /&gt;&gt; gcc -IC:\Python25\include -I -LC:\Python25\libs utils.c -lpython25&lt;br /&gt;&lt;br /&gt;Add in all the libraries and we get:&lt;br /&gt;&lt;br /&gt;gcc -IC:\Python25\include -IC:\Build\iconv-1.9.2.win32\include-IC:\Build\libxml2-2.7.2.win32\include&lt;br /&gt;&lt;div id=":up" class="ArwC7c ckChnd"&gt; -IC:\Build\libxmlsec-1.2.11.&lt;wbr&gt;win32\include&lt;br /&gt;-IC:\Build\libxslt-1.1.24.&lt;wbr&gt;win32\include&lt;br /&gt;-IC:\Build\openssl-0.9.8a.&lt;wbr&gt;win32\include&lt;br /&gt;-IC:\Build\zlib-1.2.3.win32\&lt;wbr&gt;include -LC:\Python25\libs&lt;br /&gt;-LC:\Build\iconv-1.9.2.win32\&lt;wbr&gt;lib -LC:\Build\libxml2-2.7.2.&lt;wbr&gt;win32\lib&lt;br /&gt;-LC:\Build\libxmlsec-1.2.11.&lt;wbr&gt;win32\lib&lt;br /&gt;-LC:\Build\libxslt-1.1.24.&lt;wbr&gt;win32\lib&lt;br /&gt;-LC:\Build\openssl-0.9.8a.&lt;wbr&gt;win32\lib -LC:\Build\zlib-1.2.3.win32\&lt;wbr&gt;lib&lt;br /&gt;parser.c -lpython25 -llibxml2 -llibxmlsec -llibxslt -libexslt&lt;br /&gt;-llibxmlsec-openssl -lbz2 -liconv -lzlib&lt;br /&gt;&lt;br /&gt;Looks really ugly but running it gives us a glimmer of hope:&lt;br /&gt;&lt;br /&gt;In file included from xmlsecmod.h:4,&lt;br /&gt;               from parser.c:25:&lt;br /&gt;C:/Build/libxmlsec-1.2.11.&lt;wbr&gt;win32/include/xmlsec/crypto.h:&lt;wbr&gt;54:2: #error&lt;br /&gt;No crypto library defined&lt;br /&gt;&lt;br /&gt;So we need to pick a crypto library. We do this through the gcc option -D.&lt;br /&gt;&lt;br /&gt;-DXMLSEC_CRYPTO_OPENSSL&lt;br /&gt;&lt;br /&gt;While looking for define options I also happen upon a post that said&lt;br /&gt;to define -DLIBXML_STATIC -DLIBXSLT_STATIC -DXMLSEC_STATIC.&lt;br /&gt;&lt;br /&gt;Another try:&lt;br /&gt;&lt;br /&gt;gcc -DXMLSEC_CRYPTO_OPENSSL -DLIBXML_STATIC -DLIBXSLT_STATIC&lt;br /&gt;-DXMLSEC_STATIC -IC:\Python25\include&lt;br /&gt;-IC:\Build\iconv-1.9.2.win32\&lt;wbr&gt;include&lt;br /&gt;-IC:\Build\libxml2-2.5.10.&lt;wbr&gt;win32\include&lt;br /&gt;-IC:\Build\libxmlsec-1.2.11.&lt;wbr&gt;win32\include&lt;br /&gt;-IC:\Build\libxslt-1.1.24.&lt;wbr&gt;win32\include -IC:\OpenSSL\include&lt;br /&gt;-IC:\Build\zlib-1.2.3.win32\&lt;wbr&gt;include -LC:\Python25\libs&lt;br /&gt;-LC:\Build\iconv-1.9.2.win32\&lt;wbr&gt;lib -LC:\Build\libxml2-2.5.10.&lt;wbr&gt;win32\lib&lt;br /&gt;-LC:\Build\libxmlsec-1.2.11.&lt;wbr&gt;win32\lib&lt;br /&gt;-LC:\Build\libxslt-1.1.24.&lt;wbr&gt;win32\lib -LC:\OpenSSL\lib\MinGW&lt;br /&gt;-LC:\Build\zlib-1.2.3.win32\&lt;wbr&gt;lib *.c -lpython25 -llibxml2 -llibxmlsec&lt;br /&gt;-llibxslt -llibexslt -llibxmlsec-openssl -lbz2 -liconv -lzlib&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;base64.c:(.text+0x5a1): undefined reference to `xmlMalloc'&lt;br /&gt;base64.c:(.text+0x605): undefined reference to `xmlFree'&lt;br /&gt;&lt;br /&gt;This is what you'd get if you tried to use a newer libxml2. I tried these versions:&lt;br /&gt;&lt;br /&gt;libxml2-2.7.2.win32 - Doesn't work.&lt;br /&gt;libxml2-2.6.9.win32 - Doesn't work.&lt;br /&gt;libxml2-2.5.10.win32 - Works.&lt;br /&gt;&lt;br /&gt;The last error I got was:&lt;br /&gt;/mingw/lib/libmingw32.a(main.&lt;wbr&gt;o):main.c:(.text+0xbd): undefined&lt;br /&gt;reference to `WinMain@16'&lt;br /&gt;&lt;br /&gt;To fix that I added a -shared option to gcc. I also added a -o option&lt;br /&gt;so I wouldn't just get a a.exe.&lt;br /&gt;&lt;br /&gt;gcc -DXMLSEC_CRYPTO_OPENSSL -DLIBXML_STATIC -DLIBXSLT_STATIC&lt;br /&gt;-DXMLSEC_STATIC -IC:\Python25\include&lt;br /&gt;-IC:\Build\iconv-1.9.2.win32\&lt;wbr&gt;include&lt;br /&gt;-IC:\Build\libxml2-2.5.10.&lt;wbr&gt;win32\include&lt;br /&gt;-IC:\Build\libxmlsec-1.2.11.&lt;wbr&gt;win32\include&lt;br /&gt;-IC:\Build\libxslt-1.1.24.&lt;wbr&gt;win32\include -IC:\OpenSSL\include&lt;br /&gt;-IC:\Build\zlib-1.2.3.win32\&lt;wbr&gt;include -LC:\Python25\libs&lt;br /&gt;-LC:\Build\iconv-1.9.2.win32\&lt;wbr&gt;lib -LC:\Build\libxml2-2.5.10.&lt;wbr&gt;win32\lib&lt;br /&gt;-LC:\Build\libxmlsec-1.2.11.&lt;wbr&gt;win32\lib&lt;br /&gt;-LC:\Build\libxslt-1.1.24.&lt;wbr&gt;win32\lib -LC:\OpenSSL\lib\MinGW&lt;br /&gt;-LC:\Build\zlib-1.2.3.win32\&lt;wbr&gt;lib *.c -lpython25 -llibxml2 -llibxmlsec&lt;br /&gt;-llibxslt -llibexslt -llibxmlsec-openssl -lbz2 -liconv -lzlib -shared&lt;br /&gt;-o pyxmlsec.pyd&lt;br /&gt;&lt;br /&gt;Now that I know everything compiles cleanly I decide to go back and try my luck editing setup.py. To be honest I just deleted a lot of stuff and added what I needed.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;from distutils.core import setup, Extension&lt;br /&gt;import sys, commands&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;define_macros = []&lt;br /&gt;include_dirs  = []&lt;br /&gt;library_dirs  = []&lt;br /&gt;libraries     = []&lt;br /&gt;&lt;br /&gt;define_macros.append(("XMSEC_&lt;wbr&gt;CRYPTO_OPENSSL",None))&lt;br /&gt;define_macros.append(("LIBXML_&lt;wbr&gt;STATIC",None))&lt;br /&gt;define_macros.append(("&lt;wbr&gt;LIBXSLT_STATIC",None))&lt;br /&gt;define_macros.append(("XMLSEC_&lt;wbr&gt;STATIC",None))&lt;br /&gt;&lt;br /&gt;include_dirs.append("C:\\&lt;wbr&gt;Build\\iconv-1.9.2.win32\\&lt;wbr&gt;include")&lt;br /&gt;include_dirs.append("C:\\&lt;wbr&gt;Build\\libxml2-2.5.10.win32\\&lt;wbr&gt;include")&lt;br /&gt;include_dirs.append("C:\\&lt;wbr&gt;Build\\libxmlsec-1.2.11.win32\&lt;wbr&gt;\include")&lt;br /&gt;include_dirs.append("C:\\&lt;wbr&gt;Build\\libxslt-1.1.24.win32\\&lt;wbr&gt;include")&lt;br /&gt;include_dirs.append("C:\\&lt;wbr&gt;OpenSSL\\include")&lt;br /&gt;include_dirs.append("C:\\&lt;wbr&gt;Build\\zlib-1.2.3.win32\\&lt;wbr&gt;include")&lt;br /&gt;&lt;br /&gt;library_dirs.append("C:\\&lt;wbr&gt;Build\\iconv-1.9.2.win32\\lib"&lt;wbr&gt;)&lt;br /&gt;library_dirs.append("C:\\&lt;wbr&gt;Build\\libxml2-2.5.10.win32\\&lt;wbr&gt;lib")&lt;br /&gt;library_dirs.append("C:\\&lt;wbr&gt;Build\\libxmlsec-1.2.11.win32\&lt;wbr&gt;\lib")&lt;br /&gt;library_dirs.append("C:\\&lt;wbr&gt;Build\\libxslt-1.1.24.win32\\&lt;wbr&gt;lib")&lt;br /&gt;library_dirs.append("C:\\&lt;wbr&gt;OpenSSL\\lib\\MinGW")&lt;br /&gt;library_dirs.append("C:\\&lt;wbr&gt;Build\\zlib-1.2.3.win32\\lib")&lt;br /&gt;&lt;br /&gt;libraries.append("python25")&lt;br /&gt;libraries.append("libxml2")&lt;br /&gt;libraries.append("libxmlsec")&lt;br /&gt;libraries.append("libxslt")&lt;br /&gt;libraries.append("libexslt")&lt;br /&gt;libraries.append("libxmlsec-&lt;wbr&gt;openssl")&lt;br /&gt;libraries.append("bz2")&lt;br /&gt;libraries.append("iconv")&lt;br /&gt;libraries.append("zlib")&lt;br /&gt;&lt;br /&gt;em = Extension("xmlsecmod",&lt;br /&gt;             sources = ["utils.c", "wrap_objs.c",&lt;br /&gt;                        "app.c", "base64.c", "buffer.c", "errors.c",&lt;br /&gt;                        "keyinfo.c", "keys.c", "keysdata.c", "keysmngr.c",&lt;br /&gt;                        "list.c", "membuf.c", "nodeset.c", "parser.c",&lt;br /&gt;                        "templates.c", "transforms.c", "version.c",&lt;br /&gt;                        "xmldsig.c", "xmlenc.c", "xmlsec.c", "xmltree.c",&lt;br /&gt;                        "x509.c",&lt;br /&gt;                        "xmlsecmod.c"],&lt;br /&gt;             define_macros = define_macros,&lt;br /&gt;             include_dirs  = include_dirs,&lt;br /&gt;             library_dirs  = library_dirs,&lt;br /&gt;             libraries     = libraries&lt;br /&gt;             )&lt;br /&gt;&lt;br /&gt;doclines = __doc__.split("\n")&lt;br /&gt;&lt;br /&gt;setup(name = "pyxmlsec",&lt;br /&gt;    version = "0.3.0",&lt;br /&gt;    description = doclines[0],&lt;br /&gt;    long_description = "\n" . join(doclines[2:]),&lt;br /&gt;    author = "Valery Febvre",&lt;br /&gt;    author_email = "&lt;a href="mailto:vfebvre@easter-eggs.com"&gt;vfebvre@easter-eggs.com&lt;/a&gt;",&lt;br /&gt;    license = "GNU GPL",&lt;br /&gt;    platforms = ["any"],&lt;br /&gt;    url = "&lt;a href="http://pyxmlsec.labs.libre-entreprise.org/" target="_blank"&gt;http://pyxmlsec.labs.libre-&lt;wbr&gt;entreprise.org&lt;/a&gt;",&lt;br /&gt;    ext_modules = [em],&lt;br /&gt;    py_modules = ["xmlsec", "xmlsec_strings"]&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;Ran setup.py with the following command:&lt;br /&gt;&lt;br /&gt;C:\Python25\&lt;wbr&gt;python.exe setup.py build --compiler=mingw32 install&lt;br /&gt;&lt;br /&gt;running build&lt;br /&gt;running build_py&lt;br /&gt;running build_ext&lt;br /&gt;running install&lt;br /&gt;running install_lib&lt;br /&gt;copying build\lib.win32-2.5\xmlsec.py -&gt; C:\Python25\Lib\site-packages&lt;br /&gt;copying build\lib.win32-2.5\xmlsecmod.&lt;wbr&gt;pyd -&gt; C:\Python25\Lib\site-packages&lt;br /&gt;copying build\lib.win32-2.5\xmlsec_&lt;wbr&gt;strings.py -&gt; C:\Python25\Lib\site-packages&lt;br /&gt;byte-compiling C:\Python25\Lib\site-packages\&lt;wbr&gt;xmlsec.py to xmlsec.pyc&lt;br /&gt;byte-compiling C:\Python25\Lib\site-packages\&lt;wbr&gt;xmlsec_strings.py to&lt;br /&gt;xmlsec_strings.pyc&lt;br /&gt;running install_egg_info&lt;br /&gt;Writing C:\Python25\Lib\site-packages\&lt;wbr&gt;pyxmlsec-0.3.0-py2.5.egg-info&lt;br /&gt;&lt;br /&gt;Everything looks good. Startup python and try to import xmlsec. At this point you'll probably get a few errors about missing DLLs and such.&lt;br /&gt;&lt;br /&gt;I had to install Libxml and Libxslt Python Bindings for Windows&lt;br /&gt;&lt;a href="http://users.skynet.be/sbi/libxml-python/" target="_blank"&gt;http://users.skynet.be/sbi/&lt;wbr&gt;libxml-python/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt;&gt;&gt; import xmlsec&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;File "&lt;stdin&gt;", line 1, in &lt;module&gt;&lt;br /&gt;File "xmlsec.py", line 46, in &lt;module&gt;&lt;br /&gt;  import xmlsecmod&lt;br /&gt;ImportError: DLL load failed: The specified module could not be found.&lt;br /&gt;&lt;br /&gt;A few other things I had to do:&lt;br /&gt;&lt;br /&gt;Copied C:\Build\libxmlsec-1.2.11.&lt;wbr&gt;win32\bin\libxmlsec-openssl.&lt;wbr&gt;dll to C:\Python25&lt;br /&gt;Copied C:\Build\libxmlsec-1.2.11.&lt;wbr&gt;win32\bin\libxmlsec.dll to C:\Python25&lt;br /&gt;Copied C:\Build\libxmlsec-1.2.11.&lt;wbr&gt;win32\bin\libxslt.dll to C:\Python25&lt;br /&gt;Copied C:\Build\libxmlsec-1.2.11.&lt;wbr&gt;win32\bin\libexslt.dll to C:\Python25&lt;br /&gt;Copied C:\Build\libxmlsec-1.2.11.&lt;wbr&gt;win32\bin\libxmlsec-openssl.&lt;wbr&gt;dll to C:\Python25&lt;br /&gt;&lt;br /&gt;I also downloaded a Windows dependency walker to troubleshoot some OpenSSL DLL issues. The solution was to reinstall OpenSSL and have it put its DLLs in my Windows system32 directory.&lt;br /&gt;&lt;br /&gt;C:\Python25&gt;python&lt;br /&gt;Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] on win32&lt;br /&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;br /&gt;&gt;&gt;&gt; import xmlsec&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/module&gt;&lt;/module&gt;&lt;/stdin&gt;&lt;/div&gt;&lt;br /&gt;In the end I was rewarded with a nice clean import of xmlsec. The examples even work!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2044427065375438750-316706374360955026?l=returnbooleantrue.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://returnbooleantrue.blogspot.com/feeds/316706374360955026/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2044427065375438750&amp;postID=316706374360955026' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/316706374360955026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2044427065375438750/posts/default/316706374360955026'/><link rel='alternate' type='text/html' href='http://returnbooleantrue.blogspot.com/2008/11/compiling-pyxmlsec-for-windows.html' title='Compiling PyXMLSec for Windows'/><author><name>Jeff Tchang</name><uri>http://www.blogger.com/profile/16674769228742309517</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_D1ngxQVNLdM/SUGztCbLtcI/AAAAAAAAA5w/3j3a0m1UYww/S220/l.jpg'/></author><thr:total>2</thr:total></entry></feed>
