<?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>chlab</title>
	<atom:link href="http://www.chlab.ch/blog/feed" rel="self" type="application/rss+xml" />
	<link>http://www.chlab.ch/blog</link>
	<description>Very irregular posts about web development</description>
	<lastBuildDate>Thu, 28 Apr 2016 11:31:34 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.7.9</generator>
	<item>
		<title>Connecting BitBucket with ActiveCollab</title>
		<link>http://www.chlab.ch/blog/archives/tools/connecting-bitbucket-activecollab</link>
		<comments>http://www.chlab.ch/blog/archives/tools/connecting-bitbucket-activecollab#respond</comments>
		<pubDate>Thu, 28 Apr 2016 11:31:34 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://www.chlab.ch/blog/?p=385</guid>
		<description><![CDATA[It&#8217;s a common practice to reference issues in the commit messages of version control systems. It&#8217;s great to see which issue was the reason a certain change was made to the codebase. At my former workplace, we were using BitBucket (BB) for hosting our git repos and ActiveCollab (AC) for our issue tracking. BitBucket allows you to [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>It&#8217;s a common practice to reference issues in the commit messages of version control systems. It&#8217;s great to see which issue was the reason a certain change was made to the codebase.</p>
<p>At my former workplace, we were using <a href="http://bitbucket.org" target="_blank">BitBucket</a> (BB) for hosting our git repos and <a href="https://www.activecollab.com/" target="_blank">ActiveCollab</a> (AC) for our issue tracking. BitBucket allows you to reference issues in your commit messages &#8211; but only if you&#8217;re using their issue tracker. ActiveCollab allows you to import git repositories and scan them, but configuring and maintaining them is a pain. Also, we had in place the workflow that when an issue was fixed, you had to reassign it to the user who opened it in AC. This seemed like an unnecessary manual step to me that begged to be automated, so I automated it: meet <a href="https://github.com/MediaparX/acbb_connector" target="_blank">acbb_connector</a> (great name, I know).</p>
<p>acbb_connector is a little tool that you deploy on your AC server that receives a webhook callback from BB every time a commit is made and uses the AC API to manage the issue. So you push a commit like:</p>
<pre class="brush: plain; title: ; notranslate">fixed syntax error
fixes #188</pre>
<p>and it gets parsed, fixes issue 188 of the project that corresponds to the BB repo the commit is coming from and reassigns it to the user that opened the issue.</p>
<p>Documentation on how to install and configure is <a href="https://github.com/MediaparX/acbb_connector" target="_blank">on the github page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chlab.ch/blog/archives/tools/connecting-bitbucket-activecollab/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Show changed files between two git commits</title>
		<link>http://www.chlab.ch/blog/archives/tools/show-files-git-commits</link>
		<comments>http://www.chlab.ch/blog/archives/tools/show-files-git-commits#respond</comments>
		<pubDate>Thu, 03 Dec 2015 08:22:56 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://www.chlab.ch/blog/?p=376</guid>
		<description><![CDATA[Sometimes I want to get a list of files I changed within the history of a branch (or between two commits). To find out which commits I want to use I just refer to the graph, you can use any number of tools for this such as gitx, sourcetree or even git log --graph --oneline [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Sometimes I want to get a list of files I changed within the history of a branch (or between two commits). To find out which commits I want to use I just refer to the graph, you can use any number of tools for this such as gitx, sourcetree or even <code>git log --graph --oneline --all</code>.</p>
<p>Run this command to add a git alias:</p>
<pre class="brush: bash; title: ; notranslate">
git config --global alias.changed-between '!f() { git log --pretty=&quot;%H&quot; --author=&quot;$(git config user.email)&quot; $1..$2 | while read commit_hash; do git show --oneline --name-only $commit_hash | tail -n+2; done | xargs ls 2&gt;/dev/null | sort | uniq; }; f'
</pre>
<p>Then use it like this</p>
<pre class="brush: bash; title: ; notranslate">
git changed-between 07d2882 4881cdd
</pre>
<p>Which will give you an output like:</p>
<pre class="brush: plain; title: ; notranslate">
src/AppBundle/Controller/BaseController.php
src/AppBundle/Controller/UserController.php
src/AppBundle/Entity/Address.php
src/AppBundle/Form/AddressType.php
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.chlab.ch/blog/archives/tools/show-files-git-commits/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setup Mailcatcher in Vagrant box</title>
		<link>http://www.chlab.ch/blog/archives/tools/setup-mailcatcher-vagrant-box</link>
		<comments>http://www.chlab.ch/blog/archives/tools/setup-mailcatcher-vagrant-box#comments</comments>
		<pubDate>Fri, 20 Nov 2015 12:24:53 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[vagrant]]></category>

		<guid isPermaLink="false">http://www.chlab.ch/blog/?p=340</guid>
		<description><![CDATA[I am currently refactoring some mailings in an application and as you probably know, debugging mails is a PITA. Luckily I stumbled across Mailcatcher, which runs a simple mail server and can catch mails you send to it and display them in a web gui. Since it runs on localhost, it&#8217;s a bit tricky to set it [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I am currently refactoring some mailings in an application and as you probably know, debugging mails is a PITA. Luckily I stumbled across <a title="Mailcatcher" href="http://mailcatcher.me/" target="_blank">Mailcatcher</a>, which runs a simple mail server and can catch mails you send to it and display them in a web gui.</p>
<p>Since it runs on localhost, it&#8217;s a bit tricky to set it up in a Vagrant box, where your box probably has it&#8217;s own hostname (e.g. <em>myapp.dev</em>). This blog post is written for Ubuntu 14.04 with PHP and apache.</p>
<div id="attachment_353" style="width: 460px" class="wp-caption alignnone"><a href="http://www.chlab.ch/blog/wp-content/uploads/Screen-Shot-2015-11-20-at-13.22.161.png"><img class="wp-image-353 size-medium" src="http://www.chlab.ch/blog/wp-content/uploads/Screen-Shot-2015-11-20-at-13.22.161-450x388.png" alt="" width="450" height="388" srcset="http://www.chlab.ch/blog/wp-content/uploads/Screen-Shot-2015-11-20-at-13.22.161-450x388.png 450w, http://www.chlab.ch/blog/wp-content/uploads/Screen-Shot-2015-11-20-at-13.22.161-900x777.png 900w, http://www.chlab.ch/blog/wp-content/uploads/Screen-Shot-2015-11-20-at-13.22.161.png 1019w" sizes="(max-width: 450px) 100vw, 450px" /></a><p class="wp-caption-text">Mailcatcher Web GUI</p></div>
<p>Here&#8217;s how to set up Mailcatcher in your Vagrant box.</p>
<h3>Provisioning</h3>
<p>First you need to provision your Vagrant box to install Mailcatcher. If you don&#8217;t already have a provisioning script, you can add one to your Vagrantfile like this:</p>
<pre class="brush: ruby; title: ; notranslate">
config.vm.provision :shell, path: &quot;vagrant/provision.sh&quot;
</pre>
<p>Then create vagrant/provision.sh in your project directory:</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash

# install mailcatcher (http://mailcatcher.me/)
apt-get install -y ruby-dev libsqlite3-dev
gem install mailcatcher
# enable apache proxy modules to configure a reverse proxy to mailcatchers webfrontend
sudo a2enmod proxy proxy_http proxy_wstunnel

# replace sendmail path in php.ini with catchmail path
CATCHMAIL=&quot;$(which catchmail)&quot;
sed -i &quot;s|;sendmail_path\s=.*|sendmail_path = $CATCHMAIL|&quot; /etc/php5/apache2/php.ini

# restart apache
apachectl restart
</pre>
<p>Note that I replace the default sendmail path in the php.ini* for apache with Mailcatcher&#8217;s own <em>catchmail,</em> which causes all mails to be sent there. If you also send mails from the command line (e.g. cronjobs), you&#8217;ll also need to replace sendmail in <em>/etc/php5/cli/php.ini</em>.</p>
<p>If you&#8217;re sending your mails with SMTP, you have to configure <em>smtp_port</em> instead.</p>
<p>This script is only run automatically when your box is first setup. You can run it manually by calling:</p>
<pre class="brush: bash; title: ; notranslate">vagrant provision</pre>
<p>*you could also just configure this in your apache config like:</p>
<pre class="brush: bash; title: ; notranslate">php_admin_value sendmail_path &quot;/usr/local/bin/catchmail&quot;</pre>
<p>But I feel more comfortable knowing that it&#8217;s in my php.ini and won&#8217;t suddenly start sending mails if I change around my apache config and suddenly that rule is in the wrong Directory or something.</p>
<h3>Starting Mailcatcher on &#8216;vagrant up&#8217;</h3>
<p>Just add this to your Vagrantfile to start Mailcatcher when you run vagrant up:</p>
<pre class="brush: ruby; title: ; notranslate"> config.vm.provision :shell, inline: &quot;mailcatcher&quot;, run: &quot;always&quot;</pre>
<h3>Accessing Mailcatcher web gui</h3>
<p>Since the Mailcatcher web gui, where you can view all captured mails, runs on localhost, it&#8217;s not accessible via your app or website frontend by default. This is how I configured my Apache virtualhost conf to enable this (only relevant parts):</p>
<pre class="brush: bash; title: ; notranslate">
ServerName myapp.dev

# proxy pass mailcatcher to internal webserver
ProxyRequests Off
ProxyPass /mailcatcher http://localhost:1080
ProxyPass /assets http://localhost:1080/assets
ProxyPass /messages ws://localhost:1080/messages
</pre>
<p>Then restart your apache and you should be able to access <em>myapp.dev/mailcatcher</em> in the browser.  Now any mails your app sends should be instantly displayed there instead of actually being sent.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chlab.ch/blog/archives/tools/setup-mailcatcher-vagrant-box/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Manually parse raw HTTP data with PHP</title>
		<link>http://www.chlab.ch/blog/archives/webdevelopment/manually-parse-raw-http-data-php</link>
		<comments>http://www.chlab.ch/blog/archives/webdevelopment/manually-parse-raw-http-data-php#comments</comments>
		<pubDate>Thu, 14 Jun 2012 07:32:50 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Web development]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.chlab.ch/blog/?p=309</guid>
		<description><![CDATA[How to parse multipart data manually in PHP when working with HTTP PUT requests. Luckily, PHP offers some great tools for working with data that we usually take for granted. When posting multipart form-data to a PHP script, the POST values will automatically become available as an array of values in the $_POST superglobal, the [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>How to parse multipart data manually in PHP when working with HTTP PUT requests.</p>
<p>Luckily, PHP offers some great tools for working with data that we usually take for granted. When posting multipart form-data to a PHP script, the POST values will automatically become available as an array of values in the <code>$_POST</code> superglobal, the files will automatically be processed and be made available in the <code>$_FILES</code> superglobal. Unfortunately, this doesn&#8217;t work for PUT requests. This is probably by design, as with a PUT request you are actually sending a specific file to a specific location on a server. This is supported, as is sending an url-encoded querystring as the payload. What doesn&#8217;t work out of the box though is sending multipart data in a PUT request.</p>
<p>Consider the following pseudo code on the client side:</p>
<pre class="brush: php; title: ; notranslate">
curl_setopt_array(
  CURLOPT_POSTFIELDS =&gt; array(
    'user_id' =&gt; 3,
    'post_id' =&gt; 5,
    'image' =&gt; '@/tmp/current_file'),
  CURLOPT_CUSTOMREQUEST =&gt; 'PUT'
  );
</pre>
<p>If you get rid of the <code>CURLOPT_CUSTOMREQUEST</code> bit, this will be sent as a POST, and the data will be available in the <code>$_POST</code> and <code>$_FILES</code> arrays respectively. With PUT, the data will not be parsed by PHP at all. So I wrote a method to do it manually. Unparsed multipart data looks something like this:</p>
<pre class="brush: plain; title: ; notranslate">
------------------------------b2449e94a11c
Content-Disposition: form-data; name=&quot;user_id&quot;

3
------------------------------b2449e94a11c
Content-Disposition: form-data; name=&quot;post_id&quot;

5
------------------------------b2449e94a11c
Content-Disposition: form-data; name=&quot;image&quot;; filename=&quot;/tmp/current_file&quot;
Content-Type: application/octet-stream

�����JFIF���������... a bunch of binary data
</pre>
<p>Here&#8217;s a method that will parse this:</p>
<pre class="brush: php; title: ; notranslate">
/**
 * Parse raw HTTP request data
 *
 * Pass in $a_data as an array. This is done by reference to avoid copying
 * the data around too much.
 *
 * Any files found in the request will be added by their field name to the
 * $data['files'] array.
 *
 * @param   array  Empty array to fill with data
 * @return  array  Associative array of request data
 */
function parse_raw_http_request(array &amp;$a_data)
{
  // read incoming data
  $input = file_get_contents('php://input');

  // grab multipart boundary from content type header
  preg_match('/boundary=(.*)$/', $_SERVER['CONTENT_TYPE'], $matches);

  // content type is probably regular form-encoded
  if (!count($matches))
  {
    // we expect regular puts to containt a query string containing data
    parse_str(urldecode($input), $a_data);
    return $a_data;
  }

  $boundary = $matches[1];

  // split content by boundary and get rid of last -- element
  $a_blocks = preg_split(&quot;/-+$boundary/&quot;, $input);
  array_pop($a_blocks);

  // loop data blocks
  foreach ($a_blocks as $id =&gt; $block)
  {
    if (empty($block))
      continue;

    // you'll have to var_dump $block to understand this and maybe replace \n or \r with a visibile char

    // parse uploaded files
    if (strpos($block, 'application/octet-stream') !== FALSE)
    {
      // match &quot;name&quot;, then everything after &quot;stream&quot; (optional) except for prepending newlines
      preg_match(&quot;/name=\&quot;([^\&quot;]*)\&quot;.*stream[\n|\r]+([^\n\r].*)?$/s&quot;, $block, $matches);
      $a_data['files'][$matches[1]] = $matches[2];
    }
    // parse all other fields
    else
    {
      // match &quot;name&quot; and optional value in between newline sequences
      preg_match('/name=\&quot;([^\&quot;]*)\&quot;[\n|\r]+([^\n\r].*)?\r$/s', $block, $matches);
      $a_data[$matches[1]] = $matches[2];
    }
  }
}
</pre>
<p>And here&#8217;s how to use it:</p>
<pre class="brush: php; title: ; notranslate">
$a_data = array();
parse_raw_http_request($a_data);
var_dump($a_data);
</pre>
<p>In the above example, the <code>var_dump</code> would look something like this:</p>
<pre class="brush: plain; title: ; notranslate">
Array (
  [user_id] =&gt; 3
  [post_id] =&gt; 5
  [files] =&gt; Array (
    [image] =&gt; [binary data]
  )
)
</pre>
<p>I hope this helps.</p>
<p><strong>Update</strong><br />
I&#8217;m happy to see that a few people have used the code above and some have changed it to meet their requirements. Check out <a title="PHP parse raw HTTP request" href="https://gist.github.com/jas-/5c3fdc26fedd11cb9fb5#file-stream-php" target="_blank">commenter Jas&#8217; version</a> for multiple file and input-type support.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chlab.ch/blog/archives/webdevelopment/manually-parse-raw-http-data-php/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Cache Soap envelope schema for schema validation</title>
		<link>http://www.chlab.ch/blog/archives/linux/cache-soap-envelope-schema-schema-validation</link>
		<comments>http://www.chlab.ch/blog/archives/linux/cache-soap-envelope-schema-schema-validation#respond</comments>
		<pubDate>Thu, 20 Oct 2011 13:22:13 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[soap]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.chlab.ch/blog/?p=269</guid>
		<description><![CDATA[I recently had to enable schema validation on incoming requests on a Soap API running on Zend Soap. We were having noticeably worse performance with schema validation than without &#8211; and found out that it was because of the import tag pulling in the Soap envelope schema for every request: My first thought was to [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I recently had to enable schema validation on incoming requests on a Soap API running on Zend Soap. We were having noticeably worse performance with schema validation than without &#8211; and found out that it was because of the import tag pulling in the Soap envelope schema for every request:</p>
<pre class="brush: xml; title: ; notranslate">&lt;xsd:import namespace=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot; schemaLocation=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;/&gt;</pre>
<p>My first thought was to match all the schemaLocations in the schemas and cache them manually, but it seemed to me there must be a better way..<br />
There is and it&#8217;s called a catalog.</p>
<p>&#8220;What&#8217;s a catalog&#8221; I hear you say:</p>
<blockquote><p>Basically it&#8217;s a lookup mechanism used when an entity (a file or a remote resource) references another entity. The catalog lookup is inserted between the moment the reference is recognized by the software (XML parser, stylesheet processing, or even images referenced for inclusion in a rendering) and the time where loading that resource is actually started.<br />
&#8211; <a title="xmlsoft.org" href="http://xmlsoft.org/catalog.html" target="_blank">xmlsoft.org</a></p></blockquote>
<p>So, it turns out libxml has catalog support. A catalog is basically an XML file that libxml will parse and use to map references. I was doing the schema validation with <a title="DomDocument schemaValidate" href="http://php.net/manual/en/domdocument.schemavalidate.php" target="_blank">DomDocument::schemaValidate</a> and since DomDocument uses libxml behind the scenes, this works for PHP as well. libxml2 per default looks for an xml catalog in <em>/etc/xml/catalog</em> and DomDocument is hardwired to that location as well. <strong>*</strong></p>
<p>You can add XML catalogs with a little tool called <em>xmlcatalog</em> that comes with libxml (I think). The usage is pretty straightforward, call up the man page to get an overview or <a title="xmlcatalog man page" href="http://xmlsoft.org/xmlcatalog_man.html" target="_blank">read it online</a>. Here&#8217;s how I added a catalog to map the Soap envelope schema location to a local path:</p>
<p>1. Create <em>/etc/xml</em> if it doesn&#8217;t yet exist.</p>
<p>2. Copy the Soap envelope schema from <a title="Soap envelope schema" href="http://schemas.xmlsoap.org/soap/envelope/" target="_blank">http://schemas.xmlsoap.org/soap/envelope/</a> to a local path, let&#8217;s say /etc/xml/soap-envelope-1.1.xsd</p>
<p>3. Create the catalog file (if it doesn&#8217;t exist yet) and add our new rule:</p>
<pre class="brush: bash; title: ; notranslate">xmlcatalog --create --noout --add &quot;rewriteURI&quot; &quot;http://schemas.xmlsoap.org/soap/envelope/&quot; \
&quot;file:///etc/xml/soap-envelope-1.1.xsd&quot; \
/etc/xml/catalog</pre>
<p>The file created at <em>/etc/xml/catalog</em> should then look something like:</p>
<pre class="brush: xml; title: ; notranslate">&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;!DOCTYPE catalog PUBLIC &quot;-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN&quot; &quot;http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd&quot;&gt;
&lt;catalog xmlns=&quot;urn:oasis:names:tc:entity:xmlns:xml:catalog&quot;&gt;
 &lt;rewriteURI uriStartString=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot; rewritePrefix=&quot;file:///etc/xml/soap_1.1_envelope.xsd&quot;/&gt;
&lt;/catalog&gt;</pre>
<p>4. Restart apache</p>
<p>Your schema validation should be quick as a flash after that.</p>
<p><strong>*</strong> You can change this default location by setting the <code>XML_CATALOG_FILES</code> environment variable.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chlab.ch/blog/archives/linux/cache-soap-envelope-schema-schema-validation/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
