<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
><channel><title>vedovini.net &#187; technology</title> <atom:link href="http://vedovini.net/category/technology/feed/" rel="self" type="application/rss+xml" /><link>http://vedovini.net</link> <description>Founded in 1969, building software since 1985.</description> <lastBuildDate>Thu, 03 Nov 2011 18:27:54 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <item><title>And you think 160 is not enough?</title><link>http://vedovini.net/2010/10/sms-messages-are-not-160-characters-long/</link> <comments>http://vedovini.net/2010/10/sms-messages-are-not-160-characters-long/#comments</comments> <pubDate>Tue, 19 Oct 2010 11:54:40 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[technology]]></category> <category><![CDATA[encoding]]></category> <category><![CDATA[iphone]]></category> <category><![CDATA[mobile]]></category> <category><![CDATA[sms]]></category><guid isPermaLink="false">http://vedovini.net/?p=691</guid> <description><![CDATA[SMS are not 160 characters long, they are 140 bytes long! This is what I discovered today after my SO complained that her mobile operator was charging her for SMS she never sent&#8230; And when you know how computers are working, it totally makes sense! &#8220;So what?&#8221; are you going to ask? So, this is again [...]]]></description> <content:encoded><![CDATA[<p><strong><a href="http://www.flickr.com/photos/webel/1150281459/"><img class="alignright" title="SMS by Steve Webel" src="http://farm2.static.flickr.com/1362/1150281459_9fbca61690_m_d.jpg" alt="" width="240" height="161" /></a>SMS are not 160 characters long, they are 140 <span style="text-decoration: underline;">bytes</span> long! This is what I discovered today after <strong>my SO complained that her mobile operator was charging her for SMS she never sent&#8230;</strong></strong></p><p>And when you know how computers are working, it totally makes sense!</p><p>&#8220;So what?&#8221; are you going to ask? So, this is again a nice example of character encodings drive you crazy. According to <a href="http://en.wikipedia.org/wiki/SMS#Message_size">wikipedia</a> there are 3 encodings used in text messages which respectively use 7bits, 8bits and 16bits to encode a single character.</p><p>Depending on the characters you used in your message your phone is going to decide what encoding to use, thus reducing the maximum number of characters to, respectively, 160, 140 and 70 (and even less, see later). Any extra character will lead to the splitting of your message into multiple SMS and, obviously, a raise in your bill.</p><p>By default the 7bit encoding used is <a href="http://en.wikipedia.org/wiki/GSM_03.38">GSM 03.38</a>, which has the following 128 characters alphabet: @, £, $, ¥, è, é, ù, ì, ò, Ç, LF, Ø, ø, CR, Å, å, Δ, _, Φ, Γ, Λ, Ω, Π, Ψ, Σ, Θ, Ξ, ESC, Æ, æ, ß, É, SP, !, &#8220;, #, ¤, %, &amp;, &#8216;, (, ), *, +, ,, -, ., /, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, :, ;, &lt;, =, &gt;, ?, ¡, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, Ä, Ö, Ñ, Ü, §, ¿, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, ä, ö, ñ, ü, à</p><p>If you use only those characters, then you text messages can have 160 characters, however, any character outside of this alphabet will mean the use of a different encoding. And if you are using exotic scripts, your messages will be encoded in UTF-16 and in this encoding a Chinese character, for example, will take up to 4 bytes, reducing the maximum length of you Chinese message to 35 characters max.</p><p>I guess that now that smart phones are supporting international scripts and transparently breaking up text messages, a lot of people get trapped. The only recommendation I can think of is to enable your phone to display the character count when you type text messages, I noticed that my iPhone is changing the maximum number of characters according to the encoding it&#8217;s going to use to send my message.</p><p>If you want to know more about character encodings I absolutely recommend the following article by Joel Spolsky: <a href="http://www.joelonsoftware.com/articles/Unicode.html">The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)</a></p><p><strong>UPDATE: At Stephanie&#8217;s request here is how to activate message count on your iPhone (at least on my 3GS with iOS 4.1).</strong></p><p>Go to your iPhone settings, scroll down to &#8220;Messages&#8221; then toggle &#8220;Character Count&#8221; on. When you write a text message the count will show up only if you have at least two lines of text :)</p><p><a href="http://www.flickr.com/photos/cvedovini/5098205012/"><img class="aligncenter" src="http://farm2.static.flickr.com/1389/5098205012_c0e7ee66af_d.jpg" alt="" width="500" height="250" /></a></p><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2009/05/jus-dorange-ou-citron-presse/" title="Jus d&#8217;Orange ou citron pressé?">Jus d&#8217;Orange ou citron pressé?</a></li><li><a href="http://vedovini.net/2008/04/fun-with-java-files-encoding/" title="Fun with Java files encoding">Fun with Java files encoding</a></li></ul>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2010/10/sms-messages-are-not-160-characters-long/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>How to manage Google AppEngine maintenance periods</title><link>http://vedovini.net/2010/06/how-to-manage-google-appengine-maintenance-periods/</link> <comments>http://vedovini.net/2010/06/how-to-manage-google-appengine-maintenance-periods/#comments</comments> <pubDate>Wed, 30 Jun 2010 21:38:45 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[technology]]></category> <category><![CDATA[appengine]]></category> <category><![CDATA[datastore]]></category> <category><![CDATA[decorator]]></category> <category><![CDATA[django]]></category> <category><![CDATA[gae]]></category> <category><![CDATA[maintenance]]></category> <category><![CDATA[python]]></category> <category><![CDATA[read-only]]></category><guid isPermaLink="false">http://vedovini.net/?p=645</guid> <description><![CDATA[Here is a small snippet of code that I use on applications deployed on Google AppEngine to inform users that the application is in maintenance mode. It usually happen when the AppEngine team put the datastore in read-only mode for maintenance purpose but other capabilities can be tested as well. def requires_datastore_write&#40;view&#41;: def newview&#40;request, *args, [...]]]></description> <content:encoded><![CDATA[<p><img class="alignright size-full wp-image-773" src="http://static.vedovini.net/blog/wp-content/uploads/2010/06/appengine_lowres.png" alt="AppEngine logo" width="142" height="109" /><strong>Here is a small snippet of code that I use on applications deployed on Google AppEngine to inform users that the application is in maintenance mode. </strong></p><p><strong></strong>It usually happen when the AppEngine team put the datastore in read-only mode for maintenance purpose but other capabilities can be tested as well.</p><div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> requires_datastore_write<span style="color: black;">&#40;</span>view<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> newview<span style="color: black;">&#40;</span>request, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">from</span> google.<span style="color: black;">appengine</span>.<span style="color: black;">api</span> <span style="color: #ff7700;font-weight:bold;">import</span> capabilities
        datastore_write_enabled = capabilities.<span style="color: black;">CapabilitySet</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'datastore_v3'</span>, capabilities=<span style="color: black;">&#91;</span><span style="color: #483d8b;">'write'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>.<span style="color: black;">is_enabled</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> datastore_write_enabled:
            <span style="color: #ff7700;font-weight:bold;">return</span> view<span style="color: black;">&#40;</span>request, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">shortcuts</span> <span style="color: #ff7700;font-weight:bold;">import</span> render_to_response
            <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">template</span> <span style="color: #ff7700;font-weight:bold;">import</span> RequestContext
            <span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'maintenance.html'</span>, context_instance=RequestContext<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> newview</pre></div></div><p>This is a python decorator and you can use it to decorate views that require write access to the datastore. For example:</p><div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">@requires_datastore_write
<span style="color: #ff7700;font-weight:bold;">def</span> update<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    ...</pre></div></div><p>You will need to create a Django template named<br /> <samp>maintenance.html</samp></p><p>to display a warning to your users. Mine looks like this:</p><h2>Application Maintenance</h2><div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">The LibraryThing for Facebook application is currently
in maintenance mode and some operations are temporarily unavailable.
&nbsp;
Thanks for trying back later. Sorry for the inconvenience.</pre></div></div><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2009/12/a-year-in-review/" title="A year in review">A year in review</a></li><li><a href="http://vedovini.net/2010/06/properly-uploading-files-to-amazon-s3/" title="Properly uploading files to Amazon S3">Properly uploading files to Amazon S3</a></li><li><a href="http://vedovini.net/2009/04/i-can-haz-java/" title="I Can Haz Java?">I Can Haz Java?</a></li></ul>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2010/06/how-to-manage-google-appengine-maintenance-periods/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Properly uploading files to Amazon S3</title><link>http://vedovini.net/2010/06/properly-uploading-files-to-amazon-s3/</link> <comments>http://vedovini.net/2010/06/properly-uploading-files-to-amazon-s3/#comments</comments> <pubDate>Tue, 22 Jun 2010 10:27:37 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[technology]]></category> <category><![CDATA[aws]]></category> <category><![CDATA[boto]]></category> <category><![CDATA[cssmin]]></category> <category><![CDATA[gzip]]></category> <category><![CDATA[jsmin]]></category> <category><![CDATA[minify]]></category> <category><![CDATA[python]]></category> <category><![CDATA[s3]]></category><guid isPermaLink="false">http://vedovini.net/?p=624</guid> <description><![CDATA[Here is a little script I wrote and I though ought to be shared. I use it to upload static files like images, css and javascript so that they can be served by Amazon S3 instead of the main application server (like Google App Engine). It&#8217;s written in Python and does interesting things like compressing [...]]]></description> <content:encoded><![CDATA[<p><strong>Here is a little script I wrote and I though ought to be shared. I use it to upload static files like images, css and javascript so that they can be served by Amazon S3 instead of the main application server (like Google App Engine).</strong></p><p>It&#8217;s written in Python and does interesting things like compressing and minifying what needs to be. It takes 3 arguments and as 2 options:</p><div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">Usage: s3uploader.py <span style="color: #7a0874; font-weight: bold;">&#91;</span>-xm<span style="color: #7a0874; font-weight: bold;">&#93;</span> src_folder destination_bucket_name prefix</pre></div></div><dl><dt>src_folder</dt><dd>path to the local folder containing the static files to upload</dd><dt>destination_bucket_name</dt><dd>name of the S3 bucket to upload to (e.g. static.example.com)</dd><dt>prefix</dt><dd>a prefix to use for the destination key (kind of a folder on the destination bucket, I use it to specify a release version to defeat browser caching)</dd><dt>x</dt><dd>if set, the script will set a far future expiry for all files, otherwise the S3 default will be used (one day if I remember well)</dd><dt>m</dt><dd>if set, the script will minify css and javascript files</dd></dl><p>First you will have to install some dependencies, namely boto, jsmin and cssmin. Installation procedure will depend on your OS but on my Mac I do the following:</p><div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> easy_install boto
<span style="color: #c20cb9; font-weight: bold;">sudo</span> easy_install jsmin
<span style="color: #c20cb9; font-weight: bold;">sudo</span> easy_install cssmin</pre></div></div><p>And here is the script itself:</p><div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#! /usr/bin/env python</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">sys</span>, boto, <span style="color: #dc143c;">mimetypes</span>, <span style="color: #dc143c;">zipfile</span>, <span style="color: #dc143c;">gzip</span>
<span style="color: #ff7700;font-weight:bold;">from</span> io <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">StringIO</span>, BytesIO
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">optparse</span> <span style="color: #ff7700;font-weight:bold;">import</span> OptionParser
<span style="color: #ff7700;font-weight:bold;">from</span> jsmin <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #ff7700;font-weight:bold;">from</span> cssmin <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Boto picks up configuration from the env.</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'AWS_ACCESS_KEY_ID'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'Your AWS access key id goes here'</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'AWS_SECRET_ACCESS_KEY'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'Your AWS secret access key goes here'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># The list of content types to gzip, add more if needed</span>
COMPRESSIBLE = <span style="color: black;">&#91;</span> <span style="color: #483d8b;">'text/plain'</span>, <span style="color: #483d8b;">'text/csv'</span>, <span style="color: #483d8b;">'application/xml'</span>,
                <span style="color: #483d8b;">'application/javascript'</span>, <span style="color: #483d8b;">'text/css'</span> <span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #dc143c;">parser</span> = OptionParser<span style="color: black;">&#40;</span>usage=<span style="color: #483d8b;">'usage: %prog [options] src_folder destination_bucket_name prefix'</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-x'</span>, <span style="color: #483d8b;">'--expires'</span>, action=<span style="color: #483d8b;">'store_true'</span>, <span style="color: #008000;">help</span>=<span style="color: #483d8b;">'set far future expiry for all files'</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-m'</span>, <span style="color: #483d8b;">'--minify'</span>, action=<span style="color: #483d8b;">'store_true'</span>, <span style="color: #008000;">help</span>=<span style="color: #483d8b;">'minify javascript files'</span><span style="color: black;">&#41;</span>
    <span style="color: black;">&#40;</span>options, args<span style="color: black;">&#41;</span> = <span style="color: #dc143c;">parser</span>.<span style="color: black;">parse_args</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>args<span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">3</span>:
        <span style="color: #dc143c;">parser</span>.<span style="color: black;">error</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;incorrect number of arguments&quot;</span><span style="color: black;">&#41;</span>
    src_folder = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">normpath</span><span style="color: black;">&#40;</span>args<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    bucket_name = args<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    prefix = args<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
&nbsp;
    conn = boto.<span style="color: black;">connect_s3</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    bucket = conn.<span style="color: black;">get_bucket</span><span style="color: black;">&#40;</span>bucket_name<span style="color: black;">&#41;</span>
&nbsp;
    namelist = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> root, dirs, files <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">walk</span><span style="color: black;">&#40;</span>src_folder<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> files <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #483d8b;">'.svn'</span> <span style="color: #ff7700;font-weight:bold;">in</span> root:
            path = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">relpath</span><span style="color: black;">&#40;</span>root, src_folder<span style="color: black;">&#41;</span>
            namelist += <span style="color: black;">&#91;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">normpath</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>path, f<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> files<span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Uploading %d files to bucket %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>namelist<span style="color: black;">&#41;</span>, bucket.<span style="color: black;">name</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> name <span style="color: #ff7700;font-weight:bold;">in</span> namelist:
        content = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>src_folder, name<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        key = bucket.<span style="color: black;">new_key</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>prefix, name<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">type</span>, encoding = <span style="color: #dc143c;">mimetypes</span>.<span style="color: black;">guess_type</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>
        <span style="color: #008000;">type</span> = <span style="color: #008000;">type</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #483d8b;">'application/octet-stream'</span>
        headers = <span style="color: black;">&#123;</span> <span style="color: #483d8b;">'Content-Type'</span>: <span style="color: #008000;">type</span>, <span style="color: #483d8b;">'x-amz-acl'</span>: <span style="color: #483d8b;">'public-read'</span> <span style="color: black;">&#125;</span>
        states = <span style="color: black;">&#91;</span><span style="color: #008000;">type</span><span style="color: black;">&#93;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> options.<span style="color: black;">expires</span>:
            <span style="color: #808080; font-style: italic;"># We only use HTTP 1.1 headers because they are relative to the time of download</span>
            <span style="color: #808080; font-style: italic;"># instead of being hardcoded.</span>
            headers<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Cache-Control'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'max-age %d'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">3600</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">24</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">365</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> options.<span style="color: black;">minify</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">type</span> == <span style="color: #483d8b;">'application/javascript'</span>:
            outs = <span style="color: #dc143c;">StringIO</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            JavascriptMinify<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">minify</span><span style="color: black;">&#40;</span>content, outs<span style="color: black;">&#41;</span>
            content.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            content = outs.<span style="color: black;">getvalue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span>gt<span style="color: #66cc66;">;</span> <span style="color: #ff4500;">0</span> <span style="color: #ff7700;font-weight:bold;">and</span> content<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span>:
                content = content<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span>
            content = BytesIO<span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span>
            states.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'minified'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> options.<span style="color: black;">minify</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">type</span> == <span style="color: #483d8b;">'text/css'</span>:
            outs = cssmin<span style="color: black;">&#40;</span>content.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            content.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            content = outs
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span>gt<span style="color: #66cc66;">;</span> <span style="color: #ff4500;">0</span> <span style="color: #ff7700;font-weight:bold;">and</span> content<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span>:
                content = content<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span>
            content = BytesIO<span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span>
            states.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'minified'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">type</span> <span style="color: #ff7700;font-weight:bold;">in</span> COMPRESSIBLE:
            headers<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Content-Encoding'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'gzip'</span>
            compressed = <span style="color: #dc143c;">StringIO</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            gz = <span style="color: #dc143c;">gzip</span>.<span style="color: black;">GzipFile</span><span style="color: black;">&#40;</span>filename=name, fileobj=compressed, mode=<span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span>
            gz.<span style="color: black;">writelines</span><span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span>
            gz.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            content.<span style="color: black;">close</span>
            content = BytesIO<span style="color: black;">&#40;</span>compressed.<span style="color: black;">getvalue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            states.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'gzipped'</span><span style="color: black;">&#41;</span>
&nbsp;
        states = <span style="color: #483d8b;">', '</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>states<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'- %s =&amp;gt; %s (%s)'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>name, key.<span style="color: black;">name</span>, states<span style="color: black;">&#41;</span>
        key.<span style="color: black;">set_contents_from_file</span><span style="color: black;">&#40;</span>content, headers<span style="color: black;">&#41;</span>
        content.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div><p>Thanks to Nico for the expiry trick :)</p><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2009/12/a-year-in-review/" title="A year in review">A year in review</a></li><li><a href="http://vedovini.net/2010/06/how-to-manage-google-appengine-maintenance-periods/" title="How to manage Google AppEngine maintenance periods">How to manage Google AppEngine maintenance periods</a></li></ul>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2010/06/properly-uploading-files-to-amazon-s3/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Sidewiki RSS</title><link>http://vedovini.net/2009/09/sidewiki-rss/</link> <comments>http://vedovini.net/2009/09/sidewiki-rss/#comments</comments> <pubDate>Wed, 30 Sep 2009 14:11:47 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[portfolio]]></category> <category><![CDATA[technology]]></category> <category><![CDATA[atom]]></category> <category><![CDATA[free]]></category> <category><![CDATA[google]]></category> <category><![CDATA[rss]]></category> <category><![CDATA[sidewiki]]></category> <category><![CDATA[sidewikirss]]></category><guid isPermaLink="false">http://vedovini.net/?p=415</guid> <description><![CDATA[Last week Google announced Google Sidewiki, a new service that enables anyone to comment on any page. There has been a lot of comments already about Sidewiki but the thing that instantly stroke me is the fact that there&#8217;s no easy way to keep up with what others are saying about your own pages. So [...]]]></description> <content:encoded><![CDATA[<p><a href="http://www.sidewikirss.com/"><img class="alignright size-medium wp-image-466" style="border: 1px solid black;" title="sidewikirss" src="http://static.vedovini.net/blog/wp-content/uploads/2009/09/sidewikirss-300x187.jpg" alt="Sidewiki RSS" width="300" height="187" /></a>Last week Google <a href="http://googleblog.blogspot.com/2009/09/help-and-learn-from-others-as-you.html">announced</a> <a href="http://www.google.com/sidewiki/">Google Sidewiki</a>, a new service that enables anyone to comment on any page.</p><p>There has been <a href="http://twitter.com/#search?q=sidewiki">a lot of comments</a> already about Sidewiki but the thing that instantly stroke me is the fact that there&#8217;s no easy way to keep up with what others are saying about your own pages. So I took a look at the <a href="http://code.google.com/apis/sidewiki/">Sidewiki API</a> and built the <a href="http://www.sidewikirss.com/">Sidewiki RSS</a> service.</p><p>This free service (hope you won&#8217;t mind the Google Ads) enables webmasters to get the URL to the recent Sidewiki entries for their pages. There&#8217;s even a bookmarklet that you can drop in your browser&#8217;s toolbar and use to get the feed of the page you are browsing.</p><p>Hope you will like it ;)</p><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2010/02/spare-me-the-talk-about-privacy-theyre-all-clueless-anyway/" title="Spare me the talk about privacy, they&#8217;re all clueless anyway&#8230;">Spare me the talk about privacy, they&#8217;re all clueless anyway&#8230;</a></li><li><a href="http://vedovini.net/2009/12/a-year-in-review/" title="A year in review">A year in review</a></li><li><a href="http://vedovini.net/2009/04/does-google-read-this-blog/" title="Does Google read this blog?">Does Google read this blog?</a></li></ul>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2009/09/sidewiki-rss/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>JMeter distributed testing with Amazon EC2</title><link>http://vedovini.net/2009/08/jmeter-distributed-testing-with-amazon-ec2/</link> <comments>http://vedovini.net/2009/08/jmeter-distributed-testing-with-amazon-ec2/#comments</comments> <pubDate>Mon, 17 Aug 2009 12:58:55 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[technology]]></category> <category><![CDATA[cloudcomputing]]></category> <category><![CDATA[ec2]]></category> <category><![CDATA[jmeter]]></category> <category><![CDATA[scalr]]></category> <category><![CDATA[testing]]></category><guid isPermaLink="false">http://vedovini.net/?p=400</guid> <description><![CDATA[Recently I had to setup a performance testing infrastructure for one of my client. The goal was to put their web application under heavy load to prove it was able to scale properly and do some capacity planning. I chose Apache JMeter to generate the load, created a few test plans and started to nudge [...]]]></description> <content:encoded><![CDATA[<p>Recently I had to setup a performance testing infrastructure for one of my client. The goal was to put their web application under heavy load to prove it was able to scale properly and do some capacity planning.</p><p>I chose <a href="http://jakarta.apache.org/jmeter">Apache JMeter</a> to generate the load, created a few test plans and started to nudge the application. Of course I quickly understood that my MacBook won&#8217;t be enough have the server sweat.</p><p>To serve this application we are using Amazon EC2 instances managed with the <a href="http://scalr.net">Sclar.net</a> service. One day I should write something about Scalr, but for now, enough is to say that a Scalr farm defines the configuration of a cluster of EC2 instances. Each instance in a farm belongs to a role (an EC2 AMI) and the farm defines how many instances of each role should be launched.</p><p>Since JMeter can be used in a master/slave mode (<a href="http://jakarta.apache.org/jmeter/usermanual/jmeter_distributed_testing_step_by_step.pdf">see details here</a>) I decided to use Scalr to create a farm of JMeter slaves that would put the application under pressure.</p><p>The first problem I faced is that the JMeter master and its slaves must be in the same sub-network to be able to communicate, so my JMeter farm had to define two different roles, one for the master (jmeter-master) with only one instance and one for the slaves (jmeter-slave) with as many instances as necessary.</p><p>The second problem was concerning the IP addresses of the slaves, I did not want to write down the slaves&#8217; IPs and manually enter them in the JMeter command line. By chance, with Scalr, each instance in a farm is informed of its peers&#8217; IP addresses, so I wrote a small Python script that would get those IPs and launch the JMeter master with a given test plan.</p><div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#! /usr/bin/python</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">sys</span>, <span style="color: #dc143c;">subprocess</span>, <span style="color: #dc143c;">datetime</span>
&nbsp;
JMETER_CMD = <span style="color: #483d8b;">'/usr/share/jmeter/bin/jmeter'</span>
SCRIPTS_ROOT = <span style="color: #483d8b;">'/var/testing/'</span>
<span style="color: #808080; font-style: italic;"># Instance IPs for a given role are filenames in the '/etc/aws/hosts' folder</span>
SLAVES = <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/aws/hosts/jmeter-slave'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> jmeter<span style="color: black;">&#40;</span>script<span style="color: black;">&#41;</span>:
    logname = <span style="color: #dc143c;">datetime</span>.<span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">strftime</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%Y%m%d%H%M%S'</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">'.log'</span>
    script = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>SCRIPTS_ROOT, script<span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">cmd</span> = <span style="color: black;">&#91;</span> JMETER_CMD, <span style="color: #483d8b;">'-n'</span> <span style="color: black;">&#93;</span>
    <span style="color: #dc143c;">cmd</span> += <span style="color: black;">&#91;</span> <span style="color: #483d8b;">'-t'</span>, script <span style="color: black;">&#93;</span>
    <span style="color: #dc143c;">cmd</span> += <span style="color: black;">&#91;</span> <span style="color: #483d8b;">'-R'</span>, <span style="color: #483d8b;">','</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>SLAVES<span style="color: black;">&#41;</span> <span style="color: black;">&#93;</span>
    cwd = SCRIPTS_ROOT
    <span style="color: #dc143c;">subprocess</span>.<span style="color: black;">check_call</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmd</span>, cwd=cwd, stderr=<span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>, stdout=<span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    jmeter<span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div><p>This was working pretty nicely for my simpler test plans (like the one that only GETs the home page) but as soon as I tried to POST (like during the login process) this was not enough. The thing is that the POST data that JMeter is using are not stored in the test plan itself but in companion <code>.binary</code> files, and those files are not sent by the master to the slaves like the test plans are.</p><p>I thus had to find a way to send those files by myself before the launch of the test plans. Rsync seemed the easiest thing to do, so I wrote another Python script to synchronize the slaves.</p><div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#! /usr/bin/python</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">sys</span>, <span style="color: #dc143c;">subprocess</span>
&nbsp;
SCRIPTS_ROOT = <span style="color: #483d8b;">'/var/testing/'</span>
<span style="color: #808080; font-style: italic;"># Instance IPs for a given role are filenames in the '/etc/aws/hosts' folder</span>
SLAVES = <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/aws/hosts/jmeter-slave'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> sync<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> slave <span style="color: #ff7700;font-weight:bold;">in</span> SLAVES:
        dest = <span style="color: #483d8b;">'%s:/var/testing'</span> <span style="color: #66cc66;">%</span> slave
        <span style="color: #dc143c;">cmd</span> = <span style="color: black;">&#40;</span> <span style="color: #483d8b;">'rsync'</span>, <span style="color: #483d8b;">'-r'</span>, <span style="color: #483d8b;">'-e'</span>, <span style="color: #483d8b;">'ssh -q -i /var/testing/farm.key'</span>, SCRIPT_ROOT, dest<span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">subprocess</span>.<span style="color: black;">check_call</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmd</span>, stderr=<span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>, stdout=<span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    sync<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div><p>The above script requires only three things:</p><ul><li> a valid RSA private key (here <code>/var/testing/farm.key</code>), which you can download using the Scalr.net farm&#8217;s menu</li><li>the <code>/var/testing</code> folder must already exist on the slaves</li><li>and, of course, you need to initially get the files on the master. I use <code>svn up</code>.</li></ul><p>Once you have prepared and tested everything, using one master and one slave, you can rebundle the instances you used and then start to spawn tens of slaves to stress your application.</p><p>If you have already done something similar or have ideas for improving my setup do not hesitate in letting me know in the comments :)</p><p>UPDATE: With the release of the <a href="http://aws.amazon.com/vpc/">Amazon Virtual Private Cloud</a> it should be possible now to have slaves running in the cloud and a master running on your workstation, they would all be in your own sub-network. However, you will need to find another way to synchronize the POST data with the slaves.</p><h3  class="related_post_title">Most Commented Posts</h3><ul class="related_post"><li><a href="http://vedovini.net/2010/02/sevices-apres-vente/" title="Sévices Après Vente">Sévices Après Vente</a></li><li><a href="http://vedovini.net/2009/08/jmeter-distributed-testing-with-amazon-ec2/" title="JMeter distributed testing with Amazon EC2">JMeter distributed testing with Amazon EC2</a></li><li><a href="http://vedovini.net/2008/09/google-please-no/" title="Google, please, NO!">Google, please, NO!</a></li></ul>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2009/08/jmeter-distributed-testing-with-amazon-ec2/feed/</wfw:commentRss> <slash:comments>9</slash:comments> </item> <item><title>Posting multipart form data using PHP</title><link>http://vedovini.net/2009/08/posting-multipart-form-data-using-php/</link> <comments>http://vedovini.net/2009/08/posting-multipart-form-data-using-php/#comments</comments> <pubDate>Thu, 13 Aug 2009 10:35:50 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[technology]]></category> <category><![CDATA[php multipart http]]></category><guid isPermaLink="false">http://vedovini.net/?p=357</guid> <description><![CDATA[@shvi asked me for this code over Twitter, I though it would a good idea to share it here. The following code is used to post two different fields, a simple text data named &#8220;somedata&#8221; and a file named &#8220;somefile&#8221;. Hope it helps :) $destination = &#34;http://yourdomain.com/yoururl&#34;; &#160; $eol = &#34;\r\n&#34;; $data = ''; &#160; [...]]]></description> <content:encoded><![CDATA[<p><a href="http://twitter.com/shvi">@shvi</a> asked me for this code over Twitter, I though it would a good idea to share it here.</p><p>The following code is used to post two different fields, a simple text data named &#8220;somedata&#8221; and a file named &#8220;somefile&#8221;.<br /> Hope it helps :)</p><div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$destination</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;http://yourdomain.com/yoururl&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$eol</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$mime_boundary</span><span style="color: #339933;">=</span><span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$data</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'--'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$mime_boundary</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$eol</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'Content-Disposition: form-data; name=&quot;somedata&quot;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$eol</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$eol</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;Some Data&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$eol</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'--'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$mime_boundary</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$eol</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'Content-Disposition: form-data; name=&quot;somefile&quot;; filename=&quot;filename.ext&quot;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$eol</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'Content-Type: text/plain'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$eol</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'Content-Transfer-Encoding: base64'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$eol</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$eol</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data</span> <span style="color: #339933;">.=</span> <span style="color: #990000;">chunk_split</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">base64_encode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Some file content&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$eol</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;--&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$mime_boundary</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;--&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$eol</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$eol</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// finish with two eol's!!</span>
&nbsp;
<span style="color: #000088;">$params</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'http'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
                  <span style="color: #0000ff;">'method'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'POST'</span><span style="color: #339933;">,</span>
                  <span style="color: #0000ff;">'header'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Content-Type: multipart/form-data; boundary='</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$mime_boundary</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$eol</span><span style="color: #339933;">,</span>
                  <span style="color: #0000ff;">'content'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$data</span>
               <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$ctx</span> <span style="color: #339933;">=</span> <span style="color: #990000;">stream_context_create</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #339933;">@</span><span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$destination</span><span style="color: #339933;">,</span> FILE_TEXT<span style="color: #339933;">,</span> <span style="color: #000088;">$ctx</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><h3  class="related_post_title">Most Commented Posts</h3><ul class="related_post"><li><a href="http://vedovini.net/2010/02/sevices-apres-vente/" title="Sévices Après Vente">Sévices Après Vente</a></li><li><a href="http://vedovini.net/2009/08/jmeter-distributed-testing-with-amazon-ec2/" title="JMeter distributed testing with Amazon EC2">JMeter distributed testing with Amazon EC2</a></li><li><a href="http://vedovini.net/2008/09/google-please-no/" title="Google, please, NO!">Google, please, NO!</a></li></ul>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2009/08/posting-multipart-form-data-using-php/feed/</wfw:commentRss> <slash:comments>5</slash:comments> </item> <item><title>I Can Haz Java?</title><link>http://vedovini.net/2009/04/i-can-haz-java/</link> <comments>http://vedovini.net/2009/04/i-can-haz-java/#comments</comments> <pubDate>Wed, 08 Apr 2009 17:42:49 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[technology]]></category> <category><![CDATA[eclipse]]></category> <category><![CDATA[gae]]></category> <category><![CDATA[google]]></category> <category><![CDATA[google app engine]]></category> <category><![CDATA[java]]></category> <category><![CDATA[jdo]]></category> <category><![CDATA[jpa]]></category> <category><![CDATA[servlet]]></category><guid isPermaLink="false">http://vedovini.net/?p=297</guid> <description><![CDATA[They announced it yesterday at the Google Campfire &#8217;09 (here and here) and it is today on the Google App Engine blog: Java is now supported on Google App Engine! It comes with a set of Eclipse plugins to test and deploy Java servlets, using JDO or JPA to support database access. Of course, the [...]]]></description> <content:encoded><![CDATA[<p><img class="alignright" style="border: 1px solid #cccccc;" src="http://2.bp.blogspot.com/_dLfQMJsmsaI/SdvwPx8hz5I/AAAAAAAAACY/I_DEfn6nQjc/s320/ae_gwt_java.png" alt="" width="256" height="198" />They announced it yesterday at the Google Campfire &#8217;09 (<a href="http://www.techcrunch.com/2009/04/07/live-from-google-campfire-09/">here</a> and <a href="http://www.youtube.com/view_play_list?p=DFDBB63922B90A70">here</a>) and it is <a href="http://googleappengine.blogspot.com/2009/04/seriously-this-time-new-language-on-app.html">today on the Google App Engine blog</a>: <strong>Java is now supported on Google App Engine!</strong></p><p>It comes with a set of <a href="http://code.google.com/eclipse">Eclipse plugins</a> to test and deploy Java servlets, using JDO or JPA to support database access. Of course, the database behind this is <a href="http://en.wikipedia.org/wiki/BigTable">BigTable</a>, which means that a lot of relational features are not available, but it scales!</p><p>Go <a href="http://code.google.com/appengine/docs/java/gettingstarted/">there</a> to get you started, or, if you want to know if your preferred framework will play well with GAE, go to the <a href="http://groups.google.com/group/google-appengine-java/web/will-it-play-in-app-engine">&#8220;Will it play in App Engine&#8221;</a> page.</p><p>That&#8217;s good news! Especially because we may start having more and more Java applications outside of the corporate walls.</p><p>Yes Google, YES!</p><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2010/06/how-to-manage-google-appengine-maintenance-periods/" title="How to manage Google AppEngine maintenance periods">How to manage Google AppEngine maintenance periods</a></li><li><a href="http://vedovini.net/2010/02/spare-me-the-talk-about-privacy-theyre-all-clueless-anyway/" title="Spare me the talk about privacy, they&#8217;re all clueless anyway&#8230;">Spare me the talk about privacy, they&#8217;re all clueless anyway&#8230;</a></li><li><a href="http://vedovini.net/2009/09/sidewiki-rss/" title="Sidewiki RSS">Sidewiki RSS</a></li></ul>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2009/04/i-can-haz-java/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>vedovini.net is on Facebook</title><link>http://vedovini.net/2009/03/vedovininet-is-on-facebook/</link> <comments>http://vedovini.net/2009/03/vedovininet-is-on-facebook/#comments</comments> <pubDate>Thu, 12 Mar 2009 18:14:43 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[marketing]]></category> <category><![CDATA[portfolio]]></category> <category><![CDATA[technology]]></category> <category><![CDATA[facebook]]></category> <category><![CDATA[wordpress]]></category><guid isPermaLink="false">http://vedovini.net/?p=263</guid> <description><![CDATA[As you might have noticed already, Facebook as been on vedovini.net since last December. To this purpose I have been using the Sociable! fbConnect plugin for WordPress that enables visitors to login using their Facebook credentials and later comment using their Facebook identity and feature those comments on their Facebook stream. However, I wanted a [...]]]></description> <content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/cvedovini/3348343519/"><img class="alignright" style="border: 1px solid black;" title="vedovini.net canvas page on Facebook" src="http://farm4.static.flickr.com/3549/3348343519_abd85c62c9_m_d.jpg" alt="" width="240" height="166" /></a>As you might have noticed already, Facebook as been on vedovini.net since last December. To this purpose I have been using the <a href="http://www.sociable.es/facebook-connect/">Sociable! fbConnect plugin</a> for WordPress that enables visitors to login using their Facebook credentials and later comment using their Facebook identity and feature those comments on their Facebook stream.</p><p>However, I wanted a deeper integration between this blog and my Facebook profile. Here is what I have done.</p><p>In the process of installing the fbConnect plugin you have to create a Facebook application and, among other things, Facebook applications feature a canvas page and an application tab. The canvas page is the main application page, the tab can be added to any user&#8217;s or page&#8217;s profiles.</p><p>To setup the canvas page you specify an URL that will either serve <a href="http://developers.facebook.com/">FBML</a> (Facebook markup) or pure HTML. In the latter case the page is displayed in an IFRAME.</p><p>Initially, I used the IFRAME version to display the home page but I found awkward to have my blog design mixed with the Facebook design. Additionally this technique cannot be used for tabs, that only support FBML.</p><p>Finally, I crafted <a href="http://vedovini.net/facebook">special pages</a> on this blog that serves only FBML with a special Facebook styling extracted from <a href="http://foxinni.com/my-themes/facebook-layouts-wordpress-theme/">Foxinni&#8217;s Facebook WordPress Theme</a>. The resulting canvas page can bee seen <a href="http://apps.facebook.com/vedovinidotnet/">here</a> and the corresponding profile tab is now featured on my own Facebook profile, <a href="http://www.facebook.com/cvedovini?v=app_38251350115">here</a> (you may not be able to see this one because of Facebook privacy control so I inserted a screenshot below).</p><p style="text-align: center;"><a href="http://www.flickr.com/photos/cvedovini/3349783478"><img class="aligncenter" style="border: 1px solid black;" title="vedovini.net profile tab on Facebook" src="http://farm4.static.flickr.com/3594/3349783478_6353e674b8_d.jpg" alt="" width="500" height="414" /></a></p><p>If this is getting enough interest I might package it as a WordPress plugin. Leave a comment if you are interested or if you have additional ideas.</p><p>UPDATE (2010-03-13): This is now a WordPress plugin, see my <a href="http://vedovini.net/plugins">plugins page</a>.</p><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2008/12/facebook-connect-for-wordpress/" title="Facebook connect for Wordpress">Facebook connect for Wordpress</a></li><li><a href="http://vedovini.net/2010/07/facebook-pages-notifications/" title="Facebook Pages Notifications">Facebook Pages Notifications</a></li><li><a href="http://vedovini.net/2010/01/experiencing-viral-growth/" title="Experiencing viral growth">Experiencing viral growth</a></li></ul>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2009/03/vedovininet-is-on-facebook/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>What BOINC are you?</title><link>http://vedovini.net/2009/02/what-boinc-are-you/</link> <comments>http://vedovini.net/2009/02/what-boinc-are-you/#comments</comments> <pubDate>Mon, 16 Feb 2009 15:33:36 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[technology]]></category> <category><![CDATA[boinc]]></category> <category><![CDATA[climateprediction]]></category> <category><![CDATA[einstein@home]]></category> <category><![CDATA[grid computing]]></category> <category><![CDATA[lhc@home]]></category> <category><![CDATA[seti@home]]></category><guid isPermaLink="false">http://vedovini.net/?p=251</guid> <description><![CDATA[I have been participating in the SETI@Home project since January the 6th, 2000 (at this time I was a huge fan of The X-Files and I though it may help Fox Mulder find his lost sister&#8230;). Since then I have been installing the SETI@Home client on every desktop or laptop computer I have been using. [...]]]></description> <content:encoded><![CDATA[<p><img class="alignright size-medium wp-image-252" title="SET@Home" src="http://static.vedovini.net/blog/wp-content/uploads/2009/02/800px-setiathomeversion4point45-300x223.png" alt="SET@Home" width="300" height="223" />I have been participating in the <a href="http://setiathome.berkeley.edu/">SETI@Home</a> project since January the 6th, 2000 (at this time I was a huge fan of <a href="http://en.wikipedia.org/wiki/X-Files">The X-Files</a> and I though it may help <a href="http://en.wikipedia.org/wiki/Fox_Mulder">Fox Mulder</a> find his lost sister&#8230;). Since then I have been installing the SETI@Home client on every desktop or laptop computer I have been using.</p><p>For those who do not know what the SETI@Home project is, the goal is to sort out radio signals from the <a href="http://en.wikipedia.org/wiki/Arecibo_Observatory">Arecibo radio telescope</a> using <a href="http://en.wikipedia.org/wiki/Grid_computing">grid computing</a> in order to find extraterrestrial signals.</p><p>As far as I know this was the very first large scale implementation of a grid based computer and today, with 556,888 machines and 1,393.74 TeraFLOPS per day, I think this can be considered the most powerful super-computer in the world.</p><p>We still did not find any track of <a href="http://en.wikipedia.org/wiki/Samantha_Mulder">Samantha Mulder</a>, but what this project has actually proven is that it is possible to use desktop computers idle time to do useful scientific researches.</p><p>In 2005, the SETI@Home software became <a href="http://boinc.berkeley.edu/">BOINC (Berkeley Open Infrastructure for Network Computing)</a> and mutated into a platform which is now not only supporting the SETI@Home project but many other scientific projects.</p><p>When I am not using them, my laptop and my desktop are running the following projects:</p><ul><li><a href="http://setiathome.ssl.berkeley.edu/">SETI@Home</a>: detection of extraterrestrial technology.</li><li><a href="http://climateprediction.net/">climate<em>prediction</em>.net</a>: the largest experiment to produce a forecast of the climate in the 21st century.</li><li><a href="http://www.einsteinathome.org/">Einstein@Home</a>:  gravitational waves detection.</li><li><a href="http://lhcathome.cern.ch/">LHC@Home</a>: processing <a href="http://en.wikipedia.org/wiki/Large_Hadron_Collider">LHC</a> data to detect <a href="http://en.wikipedia.org/wiki/Higgs_boson">Higgs boson</a> and other funny particles.</li></ul><p>What are you doing with your computers&#8217; idle time? If you have BOINC installed, list the projects you are supporting in the comments, if not then install it and become part of the most powerful super-computer in the Solar System ;)</p><h3  class="related_post_title">Most Commented Posts</h3><ul class="related_post"><li><a href="http://vedovini.net/2010/02/sevices-apres-vente/" title="Sévices Après Vente">Sévices Après Vente</a></li><li><a href="http://vedovini.net/2009/08/jmeter-distributed-testing-with-amazon-ec2/" title="JMeter distributed testing with Amazon EC2">JMeter distributed testing with Amazon EC2</a></li><li><a href="http://vedovini.net/2008/09/google-please-no/" title="Google, please, NO!">Google, please, NO!</a></li></ul>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2009/02/what-boinc-are-you/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Shooting in the dark</title><link>http://vedovini.net/2009/02/shooting-in-the-dark/</link> <comments>http://vedovini.net/2009/02/shooting-in-the-dark/#comments</comments> <pubDate>Wed, 04 Feb 2009 13:37:48 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[technology]]></category> <category><![CDATA[deadlines]]></category> <category><![CDATA[integration]]></category> <category><![CDATA[project management]]></category> <category><![CDATA[unit testing]]></category><guid isPermaLink="false">http://vedovini.net/?p=244</guid> <description><![CDATA[One think I hate about software is when you must integrate with a poorly documented system. To be able to code and unit test you part you have to make assumptions about the workings of this system, deploy in a real environment (which can be quite time consuming) and pray. This is like trying to [...]]]></description> <content:encoded><![CDATA[<p>One think I hate about software is when you must integrate with a poorly documented system.</p><p>To be able to code and unit test you part you have to make assumptions about the workings of this system, deploy in a real environment (which can be quite time consuming) and pray.</p><p>This is like trying to shoot a bear in the dark, if you miss it the first time it will run after you like a delivery deadline. The only thing you can do is try again until you hit or it passes you by&#8230;</p><p>If you feel any relief in sharing your dreadiest experiences feel free to comment :)</p><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2008/08/xml-schemas-compatibility/" title="XML schemas compatibility">XML schemas compatibility</a></li><li><a href="http://vedovini.net/2008/06/the-human-esb/" title="The Human ESB">The Human ESB</a></li><li><a href="http://vedovini.net/2008/05/database-schemas-compatibility/" title="Database schemas compatibility">Database schemas compatibility</a></li></ul>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2009/02/shooting-in-the-dark/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
