initial commit
authorMichael Wallner <mike@php.net>
Thu, 20 Jan 2022 19:48:47 +0000 (20:48 +0100)
committerMichael Wallner <mike@php.net>
Thu, 20 Jan 2022 19:48:47 +0000 (20:48 +0100)
108 files changed:
.gitignore [new file with mode: 0644]
404.html [new file with mode: 0644]
Gemfile [new file with mode: 0644]
Gemfile.lock [new file with mode: 0644]
LICENSE [new file with mode: 0644]
_config.yml [new file with mode: 0644]
_includes/ccsa.html [new file with mode: 0644]
_includes/foot.html [new file with mode: 0644]
_includes/head.html [new file with mode: 0644]
_includes/pubinfo.html [new file with mode: 0644]
_layouts/default.html [new file with mode: 0644]
_layouts/post.html [new file with mode: 0644]
_layouts/tags.html [new file with mode: 0644]
_plugins/tags.rb [new file with mode: 0644]
_posts/2004-08-02-javascript-flexy.md [new file with mode: 0644]
_posts/2004-08-02-scrollable-overflowauto-elements-in-mozilla.md [new file with mode: 0644]
_posts/2004-08-03-class-inheritance-or-containers.md [new file with mode: 0644]
_posts/2004-08-04-dropping-server-load-with-http-caching.md [new file with mode: 0644]
_posts/2004-08-05-update-overflowauto-in-mozilla.md [new file with mode: 0644]
_posts/2004-08-25-extapr-exercise-or-joke.md [new file with mode: 0644]
_posts/2004-09-12-hordechora-major-vulnaribility.md [new file with mode: 0644]
_posts/2004-09-13-chora-already-fixed.md [new file with mode: 0644]
_posts/2004-10-06-extvpopmail-no-thanks.md [new file with mode: 0644]
_posts/2004-10-08-pearauth-and-vpop-xmlrpc.md [new file with mode: 0644]
_posts/2005-01-27-peclhttp.md [new file with mode: 0644]
_posts/2005-03-04-peclhttp-060.md [new file with mode: 0644]
_posts/2005-06-05-moddomaintree.md [new file with mode: 0644]
_posts/2005-06-07-httprequestpool-in-peclhttp.md [new file with mode: 0644]
_posts/2005-06-29-is-php-staying-language-i-want-to-work-with.md [new file with mode: 0644]
_posts/2005-08-26-pecl-http-lap-12.md [new file with mode: 0644]
_posts/2005-09-12-tutorial-kinda-for-peclhttp.md [new file with mode: 0644]
_posts/2005-10-04-references-in-php.md [new file with mode: 0644]
_posts/2005-11-13-obviously.md [new file with mode: 0644]
_posts/2005-11-13-php-51-around-the-corner.md [new file with mode: 0644]
_posts/2005-11-16-submitting-bug-for-php.md [new file with mode: 0644]
_posts/2005-11-16-submitting-patch-for-php.md [new file with mode: 0644]
_posts/2005-11-16-time-to-say-good-bye.md [new file with mode: 0644]
_posts/2005-11-17-boost-your-website-with-apc.md [new file with mode: 0644]
_posts/2005-12-06-hash-extension.md [new file with mode: 0644]
_posts/2005-12-06-peclhttp-nasty-bug-and-new-example.md [new file with mode: 0644]
_posts/2005-12-15-peclhttp-0200-outta-door.md [new file with mode: 0644]
_posts/2005-12-30-sfluentdecorated.md [new file with mode: 0644]
_posts/2006-01-27-apache2-moddomaintree-version-13.md [new file with mode: 0644]
_posts/2006-01-27-imapsavebody.md [new file with mode: 0644]
_posts/2006-02-03-some-cool-new-features-of-peclhttp.md [new file with mode: 0644]
_posts/2006-02-15-peclhttp-update.md [new file with mode: 0644]
_posts/2006-03-07-end-of-youth.md [new file with mode: 0644]
_posts/2006-05-22-cookie-handling.md [new file with mode: 0644]
_posts/2006-05-31-konquerors-viewmode-buttons.md [new file with mode: 0644]
_posts/2006-06-09-finally.md [new file with mode: 0644]
_posts/2006-06-11-installing-peclhttp.md [new file with mode: 0644]
_posts/2006-08-18-round-up.md [new file with mode: 0644]
_posts/2006-08-21-get-and-array-rumors.md [new file with mode: 0644]
_posts/2006-09-16-httprequestdatashare.md [new file with mode: 0644]
_posts/2007-02-08-http-curl-and-stuff.md [new file with mode: 0644]
_posts/2007-02-10-something-i-didn-even-know-i-was-missing.md [new file with mode: 0644]
_posts/2007-04-01-upgrading-to-52.md [new file with mode: 0644]
_posts/2007-05-03-apache-multiviews-are-evil.md [new file with mode: 0644]
_posts/2007-05-03-two-pitfalls-in-one-afternoon.md [new file with mode: 0644]
_posts/2007-05-09-phar-vs-world.md [new file with mode: 0644]
_posts/2007-05-23-silence.md [new file with mode: 0644]
_posts/2007-09-11-introducing-libcurls-multi-socket-api.md [new file with mode: 0644]
_posts/2008-11-18-qmail-spamassassin-selectivity.md [new file with mode: 0644]
_posts/2008-11-18-vpopmail-and-people-reaching-their-maildir-quota.md [new file with mode: 0644]
_posts/2008-12-05-peclhttp-and-sub-second-timeouts.md [new file with mode: 0644]
_posts/2009-04-10-php-commandline-highlighter.md [new file with mode: 0644]
_posts/2009-04-20-looking-for-php-geeks-in-austria.md [new file with mode: 0644]
_posts/2010-05-10-websockets-handshake-non-http-conforming.md [new file with mode: 0644]
_posts/2011-03-14-courier-imap-authdaemond-and-vpopmails-vchkpw.md [new file with mode: 0644]
_posts/2011-03-18-javascript-delaying.md [new file with mode: 0644]
_posts/2013-02-19-peclhttp-v2-http2-or-httpi-or-http.md [new file with mode: 0644]
_posts/2013-03-03-peclhttp-175.md [new file with mode: 0644]
_posts/2013-06-18-hear-hear.md [new file with mode: 0644]
_posts/2013-12-09-evolution-of.md [new file with mode: 0644]
_posts/2015-08-11-testing-php-extensions-on-travis-ci.md [new file with mode: 0644]
_posts/2015-08-19-blank-dell-on-displayport.md [new file with mode: 0644]
_posts/2016-04-16-debian-disabling-sslv3-in-courier-server.md [new file with mode: 0644]
_sass/_colors.scss [new file with mode: 0644]
_sass/_common.scss [new file with mode: 0644]
_sass/_fonts.scss [new file with mode: 0644]
_sass/index.scss [new file with mode: 0644]
_sass/post.scss [new file with mode: 0644]
assets/cc-sa.png [new file with mode: 0644]
assets/index.scss [new file with mode: 0644]
assets/lapalma-c.jpg [new file with mode: 0644]
assets/lapalma-o-10.jpg [new file with mode: 0644]
assets/lapalma-o-100.jpg [new file with mode: 0644]
assets/lapalma-o-progressive.jpg [new file with mode: 0644]
assets/lapalma-o.jpg [new file with mode: 0644]
assets/post.scss [new file with mode: 0644]
assets/rouge.css [new file with mode: 0644]
assets/subset-LinBiolinum.woff [new file with mode: 0644]
assets/subset-LinBiolinum.woff2 [new file with mode: 0644]
assets/subset-LinBiolinumB.woff [new file with mode: 0644]
assets/subset-LinBiolinumB.woff2 [new file with mode: 0644]
assets/subset-LinBiolinumI.woff [new file with mode: 0644]
assets/subset-LinBiolinumI.woff2 [new file with mode: 0644]
assets/subset-LinLibertineDisplay.woff [new file with mode: 0644]
assets/subset-LinLibertineDisplay.woff2 [new file with mode: 0644]
blog.html [new file with mode: 0644]
favicon.ico [new file with mode: 0644]
index.html [new file with mode: 0644]
m6w6.jpg [new file with mode: 0644]
m6w6.png [new file with mode: 0644]
openpgp.key [new file with mode: 0644]
robots.txt [new file with mode: 0644]
x509.crt [new file with mode: 0644]
x509.key [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..62000dd
--- /dev/null
@@ -0,0 +1,9 @@
+.bundle
+.idea
+.jekyll-cache
+.jekyll-metadata
+.sass-cache
+.source
+_site
+vendor
+
diff --git a/404.html b/404.html
new file mode 100644 (file)
index 0000000..c2b8183
--- /dev/null
+++ b/404.html
@@ -0,0 +1,35 @@
+---
+permalink: /404.html
+layout: default
+styles: assets/index.css
+---
+
+<style type="text/css" media="screen">
+  .container {
+    margin: 10px auto;
+    max-width: 600px;
+    text-align: center;
+  }
+  h1 {
+    margin: 30px 0;
+    font-size: 4em;
+    line-height: 1;
+    letter-spacing: -1px;
+  }
+       html {
+               height: 100%;
+       }
+       body.default {
+               display: flex;
+               align-items: center;
+               margin: 0;
+               height: 100%;
+       }
+</style>
+
+<div class="container">
+  <h1>404</h1>
+
+  <p><strong>Page not found :(</strong></p>
+  <p>The requested page could not be found.</p>
+</div>
diff --git a/Gemfile b/Gemfile
new file mode 100644 (file)
index 0000000..97db9a2
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,11 @@
+source "https://rubygems.org"
+
+# gem "jekyll", "~> 4.2"
+# gem "github-pages"
+gem "github-pages", "~> 219", group: :jekyll_plugins
+
+group :jekyll_plugins do
+  gem "jekyll-feed"
+  gem "jekyll-sitemap"
+  gem "jekyll-relative-links"
+end
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644 (file)
index 0000000..299337e
--- /dev/null
@@ -0,0 +1,285 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    activesupport (6.0.4.1)
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      i18n (>= 0.7, < 2)
+      minitest (~> 5.1)
+      tzinfo (~> 1.1)
+      zeitwerk (~> 2.2, >= 2.2.2)
+    addressable (2.8.0)
+      public_suffix (>= 2.0.2, < 5.0)
+    coffee-script (2.4.1)
+      coffee-script-source
+      execjs
+    coffee-script-source (1.11.1)
+    colorator (1.1.0)
+    commonmarker (0.17.13)
+      ruby-enum (~> 0.5)
+    concurrent-ruby (1.1.9)
+    dnsruby (1.61.7)
+      simpleidn (~> 0.1)
+    em-websocket (0.5.2)
+      eventmachine (>= 0.12.9)
+      http_parser.rb (~> 0.6.0)
+    ethon (0.15.0)
+      ffi (>= 1.15.0)
+    eventmachine (1.2.7)
+    execjs (2.8.1)
+    faraday (1.8.0)
+      faraday-em_http (~> 1.0)
+      faraday-em_synchrony (~> 1.0)
+      faraday-excon (~> 1.1)
+      faraday-httpclient (~> 1.0.1)
+      faraday-net_http (~> 1.0)
+      faraday-net_http_persistent (~> 1.1)
+      faraday-patron (~> 1.0)
+      faraday-rack (~> 1.0)
+      multipart-post (>= 1.2, < 3)
+      ruby2_keywords (>= 0.0.4)
+    faraday-em_http (1.0.0)
+    faraday-em_synchrony (1.0.0)
+    faraday-excon (1.1.0)
+    faraday-httpclient (1.0.1)
+    faraday-net_http (1.0.1)
+    faraday-net_http_persistent (1.2.0)
+    faraday-patron (1.0.0)
+    faraday-rack (1.0.0)
+    ffi (1.15.4)
+    forwardable-extended (2.6.0)
+    gemoji (3.0.1)
+    github-pages (219)
+      github-pages-health-check (= 1.17.7)
+      jekyll (= 3.9.0)
+      jekyll-avatar (= 0.7.0)
+      jekyll-coffeescript (= 1.1.1)
+      jekyll-commonmark-ghpages (= 0.1.6)
+      jekyll-default-layout (= 0.1.4)
+      jekyll-feed (= 0.15.1)
+      jekyll-gist (= 1.5.0)
+      jekyll-github-metadata (= 2.13.0)
+      jekyll-mentions (= 1.6.0)
+      jekyll-optional-front-matter (= 0.3.2)
+      jekyll-paginate (= 1.1.0)
+      jekyll-readme-index (= 0.3.0)
+      jekyll-redirect-from (= 0.16.0)
+      jekyll-relative-links (= 0.6.1)
+      jekyll-remote-theme (= 0.4.3)
+      jekyll-sass-converter (= 1.5.2)
+      jekyll-seo-tag (= 2.7.1)
+      jekyll-sitemap (= 1.4.0)
+      jekyll-swiss (= 1.0.0)
+      jekyll-theme-architect (= 0.2.0)
+      jekyll-theme-cayman (= 0.2.0)
+      jekyll-theme-dinky (= 0.2.0)
+      jekyll-theme-hacker (= 0.2.0)
+      jekyll-theme-leap-day (= 0.2.0)
+      jekyll-theme-merlot (= 0.2.0)
+      jekyll-theme-midnight (= 0.2.0)
+      jekyll-theme-minimal (= 0.2.0)
+      jekyll-theme-modernist (= 0.2.0)
+      jekyll-theme-primer (= 0.6.0)
+      jekyll-theme-slate (= 0.2.0)
+      jekyll-theme-tactile (= 0.2.0)
+      jekyll-theme-time-machine (= 0.2.0)
+      jekyll-titles-from-headings (= 0.5.3)
+      jemoji (= 0.12.0)
+      kramdown (= 2.3.1)
+      kramdown-parser-gfm (= 1.1.0)
+      liquid (= 4.0.3)
+      mercenary (~> 0.3)
+      minima (= 2.5.1)
+      nokogiri (>= 1.10.4, < 2.0)
+      rouge (= 3.26.0)
+      terminal-table (~> 1.4)
+    github-pages-health-check (1.17.7)
+      addressable (~> 2.3)
+      dnsruby (~> 1.60)
+      octokit (~> 4.0)
+      public_suffix (>= 3.0, < 5.0)
+      typhoeus (~> 1.3)
+    html-pipeline (2.14.0)
+      activesupport (>= 2)
+      nokogiri (>= 1.4)
+    http_parser.rb (0.6.0)
+    i18n (0.9.5)
+      concurrent-ruby (~> 1.0)
+    jekyll (3.9.0)
+      addressable (~> 2.4)
+      colorator (~> 1.0)
+      em-websocket (~> 0.5)
+      i18n (~> 0.7)
+      jekyll-sass-converter (~> 1.0)
+      jekyll-watch (~> 2.0)
+      kramdown (>= 1.17, < 3)
+      liquid (~> 4.0)
+      mercenary (~> 0.3.3)
+      pathutil (~> 0.9)
+      rouge (>= 1.7, < 4)
+      safe_yaml (~> 1.0)
+    jekyll-avatar (0.7.0)
+      jekyll (>= 3.0, < 5.0)
+    jekyll-coffeescript (1.1.1)
+      coffee-script (~> 2.2)
+      coffee-script-source (~> 1.11.1)
+    jekyll-commonmark (1.3.1)
+      commonmarker (~> 0.14)
+      jekyll (>= 3.7, < 5.0)
+    jekyll-commonmark-ghpages (0.1.6)
+      commonmarker (~> 0.17.6)
+      jekyll-commonmark (~> 1.2)
+      rouge (>= 2.0, < 4.0)
+    jekyll-default-layout (0.1.4)
+      jekyll (~> 3.0)
+    jekyll-feed (0.15.1)
+      jekyll (>= 3.7, < 5.0)
+    jekyll-gist (1.5.0)
+      octokit (~> 4.2)
+    jekyll-github-metadata (2.13.0)
+      jekyll (>= 3.4, < 5.0)
+      octokit (~> 4.0, != 4.4.0)
+    jekyll-mentions (1.6.0)
+      html-pipeline (~> 2.3)
+      jekyll (>= 3.7, < 5.0)
+    jekyll-optional-front-matter (0.3.2)
+      jekyll (>= 3.0, < 5.0)
+    jekyll-paginate (1.1.0)
+    jekyll-readme-index (0.3.0)
+      jekyll (>= 3.0, < 5.0)
+    jekyll-redirect-from (0.16.0)
+      jekyll (>= 3.3, < 5.0)
+    jekyll-relative-links (0.6.1)
+      jekyll (>= 3.3, < 5.0)
+    jekyll-remote-theme (0.4.3)
+      addressable (~> 2.0)
+      jekyll (>= 3.5, < 5.0)
+      jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
+      rubyzip (>= 1.3.0, < 3.0)
+    jekyll-sass-converter (1.5.2)
+      sass (~> 3.4)
+    jekyll-seo-tag (2.7.1)
+      jekyll (>= 3.8, < 5.0)
+    jekyll-sitemap (1.4.0)
+      jekyll (>= 3.7, < 5.0)
+    jekyll-swiss (1.0.0)
+    jekyll-theme-architect (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-cayman (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-dinky (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-hacker (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-leap-day (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-merlot (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-midnight (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-minimal (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-modernist (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-primer (0.6.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-github-metadata (~> 2.9)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-slate (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-tactile (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-time-machine (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-titles-from-headings (0.5.3)
+      jekyll (>= 3.3, < 5.0)
+    jekyll-watch (2.2.1)
+      listen (~> 3.0)
+    jemoji (0.12.0)
+      gemoji (~> 3.0)
+      html-pipeline (~> 2.2)
+      jekyll (>= 3.0, < 5.0)
+    kramdown (2.3.1)
+      rexml
+    kramdown-parser-gfm (1.1.0)
+      kramdown (~> 2.0)
+    liquid (4.0.3)
+    listen (3.7.0)
+      rb-fsevent (~> 0.10, >= 0.10.3)
+      rb-inotify (~> 0.9, >= 0.9.10)
+    mercenary (0.3.6)
+    mini_portile2 (2.6.1)
+    minima (2.5.1)
+      jekyll (>= 3.5, < 5.0)
+      jekyll-feed (~> 0.9)
+      jekyll-seo-tag (~> 2.1)
+    minitest (5.14.4)
+    multipart-post (2.1.1)
+    nokogiri (1.12.5)
+      mini_portile2 (~> 2.6.1)
+      racc (~> 1.4)
+    nokogiri (1.12.5-x86_64-linux)
+      racc (~> 1.4)
+    octokit (4.21.0)
+      faraday (>= 0.9)
+      sawyer (~> 0.8.0, >= 0.5.3)
+    pathutil (0.16.2)
+      forwardable-extended (~> 2.6)
+    public_suffix (4.0.6)
+    racc (1.6.0)
+    rb-fsevent (0.11.0)
+    rb-inotify (0.10.1)
+      ffi (~> 1.0)
+    rexml (3.2.5)
+    rouge (3.26.0)
+    ruby-enum (0.9.0)
+      i18n
+    ruby2_keywords (0.0.5)
+    rubyzip (2.3.2)
+    safe_yaml (1.0.5)
+    sass (3.7.4)
+      sass-listen (~> 4.0.0)
+    sass-listen (4.0.0)
+      rb-fsevent (~> 0.9, >= 0.9.4)
+      rb-inotify (~> 0.9, >= 0.9.7)
+    sawyer (0.8.2)
+      addressable (>= 2.3.5)
+      faraday (> 0.8, < 2.0)
+    simpleidn (0.2.1)
+      unf (~> 0.1.4)
+    terminal-table (1.8.0)
+      unicode-display_width (~> 1.1, >= 1.1.1)
+    thread_safe (0.3.6)
+    typhoeus (1.4.0)
+      ethon (>= 0.9.0)
+    tzinfo (1.2.9)
+      thread_safe (~> 0.1)
+    unf (0.1.4)
+      unf_ext
+    unf_ext (0.0.8)
+    unicode-display_width (1.8.0)
+    zeitwerk (2.5.1)
+
+PLATFORMS
+  ruby
+  x86_64-linux
+
+DEPENDENCIES
+  github-pages (~> 219)
+  jekyll-feed
+  jekyll-relative-links
+  jekyll-sitemap
+
+BUNDLED WITH
+   2.2.30
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..da24792
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,385 @@
+Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
+
+Creative Commons Corporation (“Creative Commons”) is not a law firm and
+does not provide legal services or legal advice. Distribution of Creative
+Commons public licenses does not create a lawyer-client or other
+relationship. Creative Commons makes its licenses and related information
+available on an “as-is” basis. Creative Commons gives no warranties
+regarding its licenses, any material licensed under their terms and
+conditions, or any related information. Creative Commons disclaims all
+liability for damages resulting from their use to the fullest extent
+possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and
+conditions that creators and other rights holders may use to share original
+works of authorship and other material subject to copyright and certain
+other rights specified in the public license below. The following
+considerations are for informational purposes only, are not exhaustive, and
+do not form part of our licenses.
+
+Considerations for licensors: Our public licenses are intended for use by
+those authorized to give the public permission to use material in ways
+otherwise restricted by copyright and certain other rights. Our licenses
+are irrevocable. Licensors should read and understand the terms and
+conditions of the license they choose before applying it. Licensors should
+also secure all rights necessary before applying our licenses so that the
+public can reuse the material as expected. Licensors should clearly mark
+any material not subject to the license. This includes other CC-licensed
+material, or material used under an exception or limitation to copyright.
+More considerations for licensors.
+
+Considerations for the public: By using one of our public licenses, a
+licensor grants the public permission to use the licensed material under
+specified terms and conditions. If the licensor’s permission is not
+necessary for any reason–for example, because of any applicable exception
+or limitation to copyright–then that use is not regulated by the license.
+Our licenses grant only permissions under copyright and certain other
+rights that a licensor has authority to grant. Use of the licensed material
+may still be restricted for other reasons, including because others have
+copyright or other rights in the material. A licensor may make special
+requests, such as asking that all changes be marked or described. Although
+not required by our licenses, you are encouraged to respect those requests
+where reasonable. More considerations for the public. 
+Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
+Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree to
+be bound by the terms and conditions of this Creative Commons
+Attribution-NonCommercial-ShareAlike 4.0 International Public License
+("Public License"). To the extent this Public License may be interpreted as
+a contract, You are granted the Licensed Rights in consideration of Your
+acceptance of these terms and conditions, and the Licensor grants You such
+rights in consideration of benefits the Licensor receives from making the
+Licensed Material available under these terms and conditions.
+
+Section 1 – Definitions.
+       
+     a.        Adapted Material means material subject to Copyright and Similar
+     Rights that is derived from or based upon the Licensed Material and in
+     which the Licensed Material is translated, altered, arranged, transformed,
+     or otherwise modified in a manner requiring permission under the Copyright
+     and Similar Rights held by the Licensor. For purposes of this Public
+     License, where the Licensed Material is a musical work, performance, or
+     sound recording, Adapted Material is always produced where the Licensed
+     Material is synched in timed relation with a moving image.
+       
+     b.        Adapter's License means the license You apply to Your Copyright and
+     Similar Rights in Your contributions to Adapted Material in accordance with
+     the terms and conditions of this Public License.
+       
+     c.        BY-NC-SA Compatible License means a license listed at
+     creativecommons.org/compatiblelicenses, approved by Creative Commons as
+     essentially the equivalent of this Public License.
+       
+     d.        Copyright and Similar Rights means copyright and/or similar rights
+     closely related to copyright including, without limitation, performance,
+     broadcast, sound recording, and Sui Generis Database Rights, without regard
+     to how the rights are labeled or categorized. For purposes of this Public
+     License, the rights specified in Section 2(b)(1)-(2) are not Copyright and
+     Similar Rights.
+       
+     e.        Effective Technological Measures means those measures that, in the
+     absence of proper authority, may not be circumvented under laws fulfilling
+     obligations under Article 11 of the WIPO Copyright Treaty adopted on
+     December 20, 1996, and/or similar international agreements.
+       
+     f.        Exceptions and Limitations means fair use, fair dealing, and/or any
+     other exception or limitation to Copyright and Similar Rights that applies
+     to Your use of the Licensed Material.
+       
+     g.        License Elements means the license attributes listed in the name of
+     a Creative Commons Public License. The License Elements of this Public
+     License are Attribution, NonCommercial, and ShareAlike.
+       
+     h.        Licensed Material means the artistic or literary work, database, or
+     other material to which the Licensor applied this Public License.
+       
+     i.        Licensed Rights means the rights granted to You subject to the
+     terms and conditions of this Public License, which are limited to all
+     Copyright and Similar Rights that apply to Your use of the Licensed
+     Material and that the Licensor has authority to license.
+       
+     j.        Licensor means the individual(s) or entity(ies) granting rights
+     under this Public License.
+       
+     k.        NonCommercial means not primarily intended for or directed towards
+     commercial advantage or monetary compensation. For purposes of this Public
+     License, the exchange of the Licensed Material for other material subject
+     to Copyright and Similar Rights by digital file-sharing or similar means is
+     NonCommercial provided there is no payment of monetary compensation in
+     connection with the exchange.
+       
+     l.        Share means to provide material to the public by any means or
+     process that requires permission under the Licensed Rights, such as
+     reproduction, public display, public performance, distribution,
+     dissemination, communication, or importation, and to make material
+     available to the public including in ways that members of the public may
+     access the material from a place and at a time individually chosen by
+     them.
+       
+     m.        Sui Generis Database Rights means rights other than copyright
+     resulting from Directive 96/9/EC of the European Parliament and of the
+     Council of 11 March 1996 on the legal protection of databases, as amended
+     and/or succeeded, as well as other essentially equivalent rights anywhere
+     in the world.
+       
+     n.        You means the individual or entity exercising the Licensed Rights
+     under this Public License. Your has a corresponding meaning.
+
+Section 2 – Scope.
+       
+     a.        License grant.
+       
+          1. Subject to the terms and conditions of this Public License,
+          the Licensor hereby grants You a worldwide, royalty-free,
+          non-sublicensable, non-exclusive, irrevocable license to exercise the
+          Licensed Rights in the Licensed Material to:
+
+               A. reproduce and Share the Licensed Material, in whole or in
+               part, for NonCommercial purposes only; and
+       
+               B. produce, reproduce, and Share Adapted Material for
+               NonCommercial purposes only.
+       
+          2. Exceptions and Limitations. For the avoidance of doubt, where
+          Exceptions and Limitations apply to Your use, this Public License does not
+          apply, and You do not need to comply with its terms and conditions.
+       
+          3. Term. The term of this Public License is specified in Section
+          6(a).
+       
+          4. Media and formats; technical modifications allowed. The
+          Licensor authorizes You to exercise the Licensed Rights in all media and
+          formats whether now known or hereafter created, and to make technical
+          modifications necessary to do so. The Licensor waives and/or agrees not to
+          assert any right or authority to forbid You from making technical
+          modifications necessary to exercise the Licensed Rights, including
+          technical modifications necessary to circumvent Effective Technological
+          Measures. For purposes of this Public License, simply making modifications
+          authorized by this Section 2(a)(4) never produces Adapted Material.
+       
+          5. Downstream recipients.
+
+               A. Offer from the Licensor – Licensed Material. Every
+               recipient of the Licensed Material automatically receives an offer from the
+               Licensor to exercise the Licensed Rights under the terms and conditions of
+               this Public License.
+       
+               B. Additional offer from the Licensor – Adapted Material.
+               Every recipient of Adapted Material from You automatically receives an
+               offer from the Licensor to exercise the Licensed Rights in the Adapted
+               Material under the conditions of the Adapter’s License You apply.
+       
+               C. No downstream restrictions. You may not offer or impose
+               any additional or different terms or conditions on, or apply any Effective
+               Technological Measures to, the Licensed Material if doing so restricts
+               exercise of the Licensed Rights by any recipient of the Licensed Material.
+       
+          6. No endorsement. Nothing in this Public License constitutes or
+          may be construed as permission to assert or imply that You are, or that
+          Your use of the Licensed Material is, connected with, or sponsored,
+          endorsed, or granted official status by, the Licensor or others designated
+          to receive attribution as provided in Section 3(a)(1)(A)(i).
+       
+     b.        Other rights.
+       
+          1. Moral rights, such as the right of integrity, are not licensed
+          under this Public License, nor are publicity, privacy, and/or other similar
+          personality rights; however, to the extent possible, the Licensor waives
+          and/or agrees not to assert any such rights held by the Licensor to the
+          limited extent necessary to allow You to exercise the Licensed Rights, but
+          not otherwise.
+       
+          2. Patent and trademark rights are not licensed under this Public
+          License.
+       
+          3. To the extent possible, the Licensor waives any right to
+          collect royalties from You for the exercise of the Licensed Rights, whether
+          directly or through a collecting society under any voluntary or waivable
+          statutory or compulsory licensing scheme. In all other cases the Licensor
+          expressly reserves any right to collect such royalties, including when the
+          Licensed Material is used other than for NonCommercial purposes.
+
+Section 3 – License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the
+following conditions.
+
+     a.        Attribution.
+       
+          1. If You Share the Licensed Material (including in modified
+          form), You must:
+       
+               A. retain the following if it is supplied by the Licensor
+               with the Licensed Material:
+
+                    i. identification of the creator(s) of the Licensed
+                    Material and any others designated to receive attribution, in any
+                    reasonable manner requested by the Licensor (including by pseudonym if
+                    designated);
+
+                    ii.        a copyright notice;
+
+                    iii. a notice that refers to this Public License;
+
+                    iv.        a notice that refers to the disclaimer of
+                    warranties;
+
+                    v. a URI or hyperlink to the Licensed Material to the
+                    extent reasonably practicable;
+       
+               B. indicate if You modified the Licensed Material and retain
+               an indication of any previous modifications; and
+       
+               C. indicate the Licensed Material is licensed under this
+               Public License, and include the text of, or the URI or hyperlink to, this
+               Public License.
+       
+          2. You may satisfy the conditions in Section 3(a)(1) in any
+          reasonable manner based on the medium, means, and context in which You
+          Share the Licensed Material. For example, it may be reasonable to satisfy
+          the conditions by providing a URI or hyperlink to a resource that includes
+          the required information.
+       
+          3. If requested by the Licensor, You must remove any of the
+          information required by Section 3(a)(1)(A) to the extent reasonably
+          practicable.
+       
+     b.        ShareAlike.In addition to the conditions in Section 3(a), if You
+     Share Adapted Material You produce, the following conditions also apply.
+       
+          1. The Adapter’s License You apply must be a Creative Commons
+          license with the same License Elements, this version or later, or a
+          BY-NC-SA Compatible License.
+       
+          2. You must include the text of, or the URI or hyperlink to, the
+          Adapter's License You apply. You may satisfy this condition in any
+          reasonable manner based on the medium, means, and context in which You
+          Share Adapted Material.
+       
+          3. You may not offer or impose any additional or different terms
+          or conditions on, or apply any Effective Technological Measures to, Adapted
+          Material that restrict exercise of the rights granted under the Adapter's
+          License You apply.
+
+Section 4 – Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that apply to
+Your use of the Licensed Material:
+       
+     a.        for the avoidance of doubt, Section 2(a)(1) grants You the right to
+     extract, reuse, reproduce, and Share all or a substantial portion of the
+     contents of the database for NonCommercial purposes only;
+       
+     b.        if You include all or a substantial portion of the database
+     contents in a database in which You have Sui Generis Database Rights, then
+     the database in which You have Sui Generis Database Rights (but not its
+     individual contents) is Adapted Material, including for purposes of Section
+     3(b); and
+       
+     c.        You must comply with the conditions in Section 3(a) if You Share
+     all or a substantial portion of the contents of the database.
+For the avoidance of doubt, this Section 4 supplements and does not replace
+Your obligations under this Public License where the Licensed Rights
+include other Copyright and Similar Rights.
+
+Section 5 – Disclaimer of Warranties and Limitation of Liability.
+       
+     a.        Unless otherwise separately undertaken by the Licensor, to the
+     extent possible, the Licensor offers the Licensed Material as-is and
+     as-available, and makes no representations or warranties of any kind
+     concerning the Licensed Material, whether express, implied, statutory, or
+     other. This includes, without limitation, warranties of title,
+     merchantability, fitness for a particular purpose, non-infringement,
+     absence of latent or other defects, accuracy, or the presence or absence of
+     errors, whether or not known or discoverable. Where disclaimers of
+     warranties are not allowed in full or in part, this disclaimer may not
+     apply to You.
+       
+     b.        To the extent possible, in no event will the Licensor be liable to
+     You on any legal theory (including, without limitation, negligence) or
+     otherwise for any direct, special, indirect, incidental, consequential,
+     punitive, exemplary, or other losses, costs, expenses, or damages arising
+     out of this Public License or use of the Licensed Material, even if the
+     Licensor has been advised of the possibility of such losses, costs,
+     expenses, or damages. Where a limitation of liability is not allowed in
+     full or in part, this limitation may not apply to You.
+       
+     c.        The disclaimer of warranties and limitation of liability provided
+     above shall be interpreted in a manner that, to the extent possible, most
+     closely approximates an absolute disclaimer and waiver of all liability.
+
+Section 6 – Term and Termination.
+       
+     a.        This Public License applies for the term of the Copyright and
+     Similar Rights licensed here. However, if You fail to comply with this
+     Public License, then Your rights under this Public License terminate
+     automatically.
+       
+     b.        Where Your right to use the Licensed Material has terminated under
+     Section 6(a), it reinstates:
+       
+          1.   automatically as of the date the violation is cured, provided
+          it is cured within 30 days of Your discovery of the violation; or
+       
+          2.   upon express reinstatement by the Licensor.
+       
+     c.        For the avoidance of doubt, this Section 6(b) does not affect any
+     right the Licensor may have to seek remedies for Your violations of this
+     Public License.
+       
+     d.        For the avoidance of doubt, the Licensor may also offer the
+     Licensed Material under separate terms or conditions or stop distributing
+     the Licensed Material at any time; however, doing so will not terminate
+     this Public License.
+       
+     e.        Sections 1, 5, 6, 7, and 8 survive termination of this Public
+     License.
+
+Section 7 – Other Terms and Conditions.
+       
+     a.        The Licensor shall not be bound by any additional or different
+     terms or conditions communicated by You unless expressly agreed.
+       
+     b.        Any arrangements, understandings, or agreements regarding the
+     Licensed Material not stated herein are separate from and independent of
+     the terms and conditions of this Public License.
+
+Section 8 – Interpretation.
+       
+     a.        For the avoidance of doubt, this Public License does not, and shall
+     not be interpreted to, reduce, limit, restrict, or impose conditions on any
+     use of the Licensed Material that could lawfully be made without permission
+     under this Public License.
+       
+     b.        To the extent possible, if any provision of this Public License is
+     deemed unenforceable, it shall be automatically reformed to the minimum
+     extent necessary to make it enforceable. If the provision cannot be
+     reformed, it shall be severed from this Public License without affecting
+     the enforceability of the remaining terms and conditions.
+       
+     c.        No term or condition of this Public License will be waived and no
+     failure to comply consented to unless expressly agreed to by the Licensor.
+       
+     d.        Nothing in this Public License constitutes or may be interpreted as
+     a limitation upon, or waiver of, any privileges and immunities that apply
+     to the Licensor or You, including from the legal processes of any
+     jurisdiction or authority.
+
+Creative Commons is not a party to its public licenses. Notwithstanding,
+Creative Commons may elect to apply one of its public licenses to material
+it publishes and in those instances will be considered the “Licensor.”
+Except for the limited purpose of indicating that material is shared under
+a Creative Commons public license or as otherwise permitted by the Creative
+Commons policies published at creativecommons.org/policies, Creative
+Commons does not authorize the use of the trademark “Creative Commons”
+or any other trademark or logo of Creative Commons without its prior
+written consent including, without limitation, in connection with any
+unauthorized modifications to any of its public licenses or any other
+arrangements, understandings, or agreements concerning use of licensed
+material. For the avoidance of doubt, this paragraph does not form part of
+the public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
diff --git a/_config.yml b/_config.yml
new file mode 100644 (file)
index 0000000..36fbf51
--- /dev/null
@@ -0,0 +1,77 @@
+title: Michael Wallner (m6w6)
+blog: "Mike's sudden inspirations"
+email: mike@php.net
+description: >-
+  C/C++ writer.
+  PHP partisan.
+  Postgres fan.
+  GNU/Linux hacker.
+  Webophilic op.
+  <br>
+  Father of two.
+  Wide open throttle.
+  Photographer in another life.
+baseurl: "/"
+url: "" # the base hostname & protocol for your site, e.g. http://example.com
+twitter_username: _m6w6
+github_username:  m6w6
+
+# Build settings
+#theme: minima
+plugins:
+  - jekyll-feed
+  - jekyll-relative-links
+  - jekyll-sitemap
+
+relative_links:
+  enabled:     true
+  collections: true
+
+kramdown:
+  input: GFM
+  syntax_highlighter_opts:
+    default_lang: shell
+#    css_class: 'highlight'
+    span:
+      line_numbers: false
+    block:
+      line_numbers: false
+      start_line: 1
+
+defaults:
+  -
+    scope:
+      path: ""
+      type: "posts"
+    values:
+      layout: "post"
+      permalink: ":year/:month/:title.html"
+      styles:
+        - "assets/post.css"
+        - "assets/rouge.css"
+
+# Exclude from processing.
+# The following items will not be processed, by default.
+# Any item listed under the `exclude:` key here will be automatically added to
+# the internal "default list".
+#
+# Excluded items can be processed by explicitly listing the directories or
+# their entries' file path in the `include:` list.
+#
+exclude:
+#   - .sass-cache/
+#   - .jekyll-cache/
+#   - gemfiles/
+#   - Gemfile
+#   - Gemfile.lock
+#   - node_modules/
+#   - vendor/
+#   - vendor/cache/
+#   - vendor/gems/
+#   - vendor/ruby/
+  - "[Gg]em*"
+  - ".idea/"
+  - "vendor/"
+  - "*cache*/"
+  - "node*/"
+
diff --git a/_includes/ccsa.html b/_includes/ccsa.html
new file mode 100644 (file)
index 0000000..f181a4e
--- /dev/null
@@ -0,0 +1,11 @@
+<p class="cc-sa">
+
+               This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"
+                       >Creative Commons Attribution-ShareAlike 4.0 International License</a>.
+
+       <br>
+       <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"
+               ><img alt="Creative Commons Share Alike License" src="assets/cc-sa.png"
+               ></a>
+
+</p>
diff --git a/_includes/foot.html b/_includes/foot.html
new file mode 100644 (file)
index 0000000..5f85cab
--- /dev/null
@@ -0,0 +1 @@
+</html>
diff --git a/_includes/head.html b/_includes/head.html
new file mode 100644 (file)
index 0000000..04d6936
--- /dev/null
@@ -0,0 +1,19 @@
+<!doctype html>
+<html lang="en">
+       <head>
+               <meta charset="utf8">
+               <title>{{ page.title }} &mdash; {{ site.title }}</title>
+               <meta name="robots" content="index, follow">
+               <meta name="viewport" content="width=device-width, initial-scale=1">
+               <base href="{{ site.baseurl }}">
+               {% feed_meta %}
+               <link rel="icon" href="m6w6.png">
+{% for style in page.styles %}
+               <link rel="stylesheet" href="{{ style }}">
+{% endfor %}
+
+{% for script in page.scripts %}
+               <script src="{{ script }}" async></script>
+{% endfor %}
+               <style>body { display: none }</style>
+       </head>
diff --git a/_includes/pubinfo.html b/_includes/pubinfo.html
new file mode 100644 (file)
index 0000000..7bdc4f0
--- /dev/null
@@ -0,0 +1,12 @@
+                       <div class="pubinfo">
+                               <p>
+                               Posted by <em>{{ page.author }}</em>
+                               on {{ page.date | date_to_long_string: "ordinal" }}
+                               in <a href="blog.html">{{ site.blog }}</a>:
+                               {% assign last_tag = page.tags | last %}
+                               {% for tag in page.tags %}
+                                       <a class="tag" href="@{{ tag }}.html"
+                                       >{{ tag }}</a>{% if tag != last_tag %}, {% endif %}
+                               {% endfor %}
+                               </p>
+                       </div>
diff --git a/_layouts/default.html b/_layouts/default.html
new file mode 100644 (file)
index 0000000..a443452
--- /dev/null
@@ -0,0 +1,7 @@
+{% include head.html %}
+       <body class="default">
+               <div>
+               {{ content }}
+               </div>
+       </body>
+{% include foot.html %}
diff --git a/_layouts/post.html b/_layouts/post.html
new file mode 100644 (file)
index 0000000..1c69c0b
--- /dev/null
@@ -0,0 +1,28 @@
+{% include head.html %}
+
+<body class="post">
+
+<div>
+       <header>
+               <h1>{{ page.title }}</h1>
+               <div aria-hidden="true">
+                       <span title="minimize">_</span>
+                       <span title="maximize">☐</span>
+                       <span title="close">☒</span>
+               </div>
+       </header>
+       <main>
+               <div>
+                       {% include pubinfo.html %}
+                       {{ content }}
+               </div>
+       </main>
+</div>
+
+<footer>
+       {% include ccsa.html %}
+</footer>
+
+</body>
+
+{% include foot.html %}
diff --git a/_layouts/tags.html b/_layouts/tags.html
new file mode 100644 (file)
index 0000000..48538ee
--- /dev/null
@@ -0,0 +1,37 @@
+---
+layout: default
+styles: assets/index.css
+---
+<header>
+       <h1>{{ page.title }}</h1>
+       <p class="breadcrumbs">
+               » <a href="blog.html">{{ site.blog }}</a>
+       </p>
+</header>
+<main>
+       <h2>#{{ page.tag }}</h2>
+       <ul>
+               {% for post in site.posts %}
+                       {% if post.tags contains page.tag %}
+               <li>
+                       <a class="post" href="{{ post.url }}">{{ post.title }}</a>
+                       &mdash; posted {{ post.date | date_to_long_string: "ordinal" }}
+               </li>
+                       {% endif %}
+               {% endfor %}
+       </ul>
+       <h2>See also</h2>
+       <p>
+               Posts in
+               {% assign last_tag = page.all_tags | last %}
+               {% for tag in page.all_tags %}
+                       {% if tag != page.tag %}
+                               {% if tag == last_tag %}
+               and
+                               {% endif %}
+               <a class="tag" href="@{{ tag }}.html"
+               >{{ tag }}</a>{% if tag != last_tag %}, {% endif %}
+                       {% endif %}
+               {% endfor %}
+       </p>
+</main>
diff --git a/_plugins/tags.rb b/_plugins/tags.rb
new file mode 100644 (file)
index 0000000..9466f6c
--- /dev/null
@@ -0,0 +1,28 @@
+module Tags
+  class TagPageGenerator < Jekyll::Generator
+    safe true
+
+    def generate(site)
+      tags = site.posts.docs.flat_map { |post| post.data['tags'] || [] }.uniq
+      tags.to_set.each do |tag|
+        site.pages << TagPage.new(site, site.source, tag, tags)
+      end
+    end
+  end
+
+  class TagPage < Jekyll::Page
+    def initialize(site, base, tag, tags)
+      @site = site
+      @base = base
+      @dir  = ""
+      @name = "@#{tag}.html"
+
+      self.process(@name)
+      self.read_yaml(base, File.join("_layouts", "tags.html"))
+      self.data['tag'] = tag
+      self.data['title'] = "Posts in #{tag}"
+      self.data['permalink'] = "@#{tag}.html"
+      self.data['all_tags'] = tags
+    end
+  end
+end
diff --git a/_posts/2004-08-02-javascript-flexy.md b/_posts/2004-08-02-javascript-flexy.md
new file mode 100644 (file)
index 0000000..2dfdf52
--- /dev/null
@@ -0,0 +1,47 @@
+---
+title: Javascript & Flexy
+author: m6w6
+tags:
+- PHP
+---
+
+If you ever used [Flexy](http://pear.php.net/package/HTML_Template_Flexy),
+which I consider a really great TE, you have most probably already stumbled
+across Flexy's inability to step into `<script>` blocks.
+
+A really easy method to overcome this problem is to define scriptOpen and
+scriptClose properties in your base objects outputted by Flexy:
+
+```php
+<?php
+class FlexyObject {
+  var $scriptOpen = "\n<script type="text/javascript"> <!--\n";
+  var $scriptClose = "\n//--> </script>n";
+  var $scriptData = "var foo = 'bar';";
+}
+```
+
+Outputting above object with the following template wont work:
+
+```html
+<html>
+<script type="text/javascript">
+  {scriptData:h}
+</script>
+</html>
+```
+
+Instead:
+
+```html
+<html>
+{scriptOpen:h}
+  {scriptData:h}
+{scriptClose:h}
+</html>
+```
+
+...works like a charm... ;)
+
+Alan said, Flexy wont step into Javascript blocks because that caused
+massive problems with the Smarty convertor...
diff --git a/_posts/2004-08-02-scrollable-overflowauto-elements-in-mozilla.md b/_posts/2004-08-02-scrollable-overflowauto-elements-in-mozilla.md
new file mode 100644 (file)
index 0000000..9e3ee18
--- /dev/null
@@ -0,0 +1,40 @@
+---
+title: Scrollable overflow:auto Elements in Mozilla
+author: m6w6
+tags:
+- WEB
+---
+
+Doing some extensive Javascript work lately, I managed to make HTML elements
+styled with //overflow:auto// scrollable in Mozilla.
+
+
+
+Just place this snippet at the bottom of your page with DIV elements that have
+scroll as classname:
+
+
+```js
+// enable scrolling for overflow:auto elements in Mozilla
+function scrollMe(event)
+{
+  var st = event.currentTarget.scrollTop;
+  st += (event.detail * 12);
+  event.currentTarget.scrollTop = st < 0 ? 0 : st;
+  event.preventDefault();
+}
+if (document.body.addEventListener) {
+  var divs = document.getElementsByTagName('DIV');
+  for (var d in divs) {
+    if (divs[d].className && divs[d].className == 'scroll') {
+      try {
+        divs[d].addEventListener(
+             'DOMMouseScroll', scrollMe, false);
+      } catch (ex) {}
+    }
+  }
+}
+```
+
+
+I already posted a feature request to embed something similar in pearweb.
diff --git a/_posts/2004-08-03-class-inheritance-or-containers.md b/_posts/2004-08-03-class-inheritance-or-containers.md
new file mode 100644 (file)
index 0000000..682bfdc
--- /dev/null
@@ -0,0 +1,54 @@
+---
+title: Class inheritance or Containers?
+author: m6w6
+tags:
+- PHP
+---
+
+While talking with Daniel and Lorenzo about "Tree Reincarnated" I regularly
+stumble across the question what approach to use to implement different
+backends: **"Class inheritance or Containers?"**.
+
+I personally feel that using the container approach leads to massive code
+duplication, while using class inheritance avoids the most (_most_, because
+there's no real multiple class inheritance in PHP).
+
+## Container
+```php
+    class PublicAPI
+    {
+        var $container; // SpecificAPI
+
+        function doSomething()
+        {
+            return $this->container->doSomething();
+        }
+    }
+```
+
+## Class Inheritance
+
+```php
+    class SpecificAPI extends PublicAPI
+    {
+        function doSomething()
+        {
+            // do something only this class needs to do
+        }
+    }
+    ?>
+```
+
+So what do you feel about this topic and how you'd handle that?
+
+## UPDATE
+
+While looking again at Daniel's [nice diagram](http://devel.webcluster.at/~daniel/pear/Tree/docs/Tree.png?),
+I feel like we've already reached the point where solving this problem with class
+inheritence is impossible (despite using aggregate*() - you're right Lorenzo,
+again :) have nice holidays! ).
+
+Tree_Admin_Simple_MDB2 would have to extend Tree_Simple_MDB2 **and**
+Tree_Admin_Simple_RDBMS...
+
+Mike's arrived at the dead end, again ;)
diff --git a/_posts/2004-08-04-dropping-server-load-with-http-caching.md b/_posts/2004-08-04-dropping-server-load-with-http-caching.md
new file mode 100644 (file)
index 0000000..d75a4b4
--- /dev/null
@@ -0,0 +1,42 @@
+---
+title: Dropping server load with HTTP caching
+author: m6w6
+tags:
+- PHP
+---
+
+Ever watched youself browsing e.g. a web forum?
+Noticed that you viewed the same page several times?
+
+Well, this means extraordinary **and** useless load for your server if there's
+no caching mechanism implemented in the web application. Even if there is some
+file or db cache you can still improve performance with implementing some http
+cache.
+
+The easiest way is using PEARs
+[HTTP::Header](http://pear.php.net/package/HTTP_Header):
+
+```php
+require_once 'HTTP/Header/Cache.php';
+// only cache a few seconds for frequently
+// changing pages like a forum;
+// Header_Cache will exit automatically with
+// "HTTP 304 Not Modified" if the page is
+// requested twice within 3 seconds
+$cache = &new HTTP_Header_Cache(3, 'seconds');
+$cache->sendHeaders();
+
+// ... load from file/db cache
+// ... or rebuild page
+```
+
+~~Probably the greatest caveat of using HTTP caching is, that our _beloved_
+Internet Explorer with standard settings doesn't even send an request to the
+server if it just **notices** a "Last-Modified" header (sic!), so one'd have
+to press the reload button (without CTRL) that a new page is displayed after
+the defined amount of time.~~
+
+~~A dead end again? Decide yourself...~~
+
+I finally managed to implement support for Internet Explorer in HTTP_Header
+1.1.0 :D
diff --git a/_posts/2004-08-05-update-overflowauto-in-mozilla.md b/_posts/2004-08-05-update-overflowauto-in-mozilla.md
new file mode 100644 (file)
index 0000000..292891d
--- /dev/null
@@ -0,0 +1,22 @@
+---
+title: 'Update: overflow:auto in Mozilla'
+author: m6w6
+tags:
+- WEB
+---
+
+If you want the page to scroll when the scrolling-enabled DIV has nothing to
+scroll you'll have to wrap the contents of the _scrollMe_ function into the
+following **if** statement:
+
+```js
+    function scrollMe(event)
+    {
+        if (event.currentTarget.scrollHeight >
+            event.currentTarget.offsetHeight) {
+            // ...
+        }
+    }
+```
+
+Have fun!
diff --git a/_posts/2004-08-25-extapr-exercise-or-joke.md b/_posts/2004-08-25-extapr-exercise-or-joke.md
new file mode 100644 (file)
index 0000000..92d2652
--- /dev/null
@@ -0,0 +1,35 @@
+---
+title: ext/apr - exercise or joke?
+author: m6w6
+tags:
+- PHP
+---
+
+Well yes, it started as an exercise (and others thought it is a joke) ;)
+
+My intention was to export apr_md5_encode() to php which generates MD5
+password hashes similar to those found in .htpasswd files. [PEARs
+File_Passwd](http://pear.php.net/package/File_Passwd) already does that, but
+with plain vanilla PHP - generating one password takes about 0.2 seconds and
+more.
+
+Currently I'm trying to make apr_threads usable - wouldn't threads in PHP be
+cool? Yes, they'd definitly be :) It's just a segfault away from working ;)
+
+```php
+    class Thread1 extends APR_Thread {
+        function run() {
+            // do some work
+        }
+    }
+    class Thread2 extends APR_Thread {
+        function run() {
+            // do some concurrent work
+        }
+    }
+    new Thread1;
+    new Thread2;
+```
+
+Thanks to Derick, Sara and the whole php.pecl gang - I wouldn't have managed
+to get that far without their tremendous help!
diff --git a/_posts/2004-09-12-hordechora-major-vulnaribility.md b/_posts/2004-09-12-hordechora-major-vulnaribility.md
new file mode 100644 (file)
index 0000000..afe8257
--- /dev/null
@@ -0,0 +1,19 @@
+---
+title: HORDE::Chora major vulnaribility
+author: m6w6
+tags: 
+- PHP
+---
+
+If you're running Hordes Chora **1.2** you should immediately upgrade your
+Horde installation or temporarily disable CVS access through HTTP.
+
+
+### Unfiltered $_GET as shell argument  
+On a quick glance scripts like _diff.php_ seem to use unfiltered $_GET
+parameters as shell command arguments, which will allow any remote user to
+execute any command as webserver user.
+
+A request like ~~<http://cvs.your.host/>... ~~ will reveal the process list of
+the machine.
+
diff --git a/_posts/2004-09-13-chora-already-fixed.md b/_posts/2004-09-13-chora-already-fixed.md
new file mode 100644 (file)
index 0000000..3326172
--- /dev/null
@@ -0,0 +1,29 @@
+---
+title: Chora already fixed
+author: m6w6
+tags:
+- PHP
+---
+
+[Jan](http://janschneider.de/cweb/home/index,channel,25,story,175.html)
+reported that Chora is already fixed for three months.
+
+
+First of all, let me apologize, I didn't want to hurt
+[Horde](http://horde.org) or anyone else, and if you found my posting
+confusing, then well, I was confused and not too little...
+
+That weekend my server has been cracked again, and ctorrent has been installed
+to burn my traffic (from the same network 210.5.125.*).
+
+I doubt that the
+[announcement](http://lists.horde.org/archives/announce/2004/000100.html) Jan
+posted helped much, because how comes that apparently every script-kiddy knew
+about the vulnaribility but not chora users (at least I didn't know, and I saw
+a lot of chora 1.2 installations out there).
+
+If I would have found a note on [Chora's homepage](http://www.horde.org/chora/), 
+I think, I wouldn't have posted such a panic reaction.
+
+So, sorry once again and I hope that this was - at least - a lesson to
+everyone of us...
diff --git a/_posts/2004-10-06-extvpopmail-no-thanks.md b/_posts/2004-10-06-extvpopmail-no-thanks.md
new file mode 100644 (file)
index 0000000..afc47fd
--- /dev/null
@@ -0,0 +1,131 @@
+---
+title: ext/vpopmail? no thanks...
+author: m6w6
+tags: 
+- PHP
+---
+
+If you ever thought about administering vpopmail through PHP, you most
+probably already stumbled across the [vpopmail](http://pecl.php.net/vpopmail)
+extension living in [PECL](http://pecl.php.net/), and know that making use of
+it is rather kludgy...
+
+In need of such a solution I've written a simple XML-RPC CGI service in C with
+help of the [xmlrpc-c](http://xmlrpc-c.sourceforge.net/) library. I really
+didn't think that it would be that easy, but it definitely was, considering
+that I'm a C novice ;)
+
+The following source will show that it's quite as simple as writing this XML-
+RPC backend in PHP, and it's really fast.
+
+### Update
+There's now a source tarball available at: <http://dev.iworks.at/vpop-xmlrpc/>  
+```c  
+#include <sys/types.h>  
+#include <stdio.h>  
+#include <stdlib.h>  
+#include <vauth.h>  
+#include <vpopmail.h>  
+#include <xmlrpc.h>  
+#include <xmlrpc_cgi.h>
+
+static xmlrpc_value *vpop_adduser(xmlrpc_env *env, xmlrpc_value *param, void *data)  
+{
+    char *user, *domain, *password, *fullname;  
+    xmlrpc_bool rs;
+    
+    xmlrpc_parse_value(env, param, "({s:s,s:s,s:s,s:s,*})",  
+        "user", &user,  
+        "domain", &domain,  
+        "password", &password,  
+        "fullname", &fullname  
+    );
+      
+    if (env->fault_occurred) {  
+        return NULL;  
+    }
+    
+    rs = vadduser(user, domain, password, fullname, 0) == 0 ? 1 : 0;
+    
+    return xmlrpc_build_value(env, "b", rs);  
+}
+
+static xmlrpc_value *vpop_deluser(xmlrpc_env *env, xmlrpc_value *param, void *data)  
+{  
+    char *user, *domain;  
+    xmlrpc_bool rs;
+    
+    xmlrpc_parse_value(env, param, "({s:s,s:s,*})",  
+        "user", &user,  
+        "domain", &domain  
+    );
+    
+    if (env->fault_occurred) {  
+        return NULL;  
+    }
+    
+    rs = vdeluser(user, domain) == 0 ? 1 : 0;
+    
+    return xmlrpc_build_value(env, "b", rs);  
+}
+
+static xmlrpc_value *vpop_passwd(xmlrpc_env *env, xmlrpc_value *param, void *data)  
+{  
+    char *user, *domain, *password;  
+    xmlrpc_bool rs;
+    
+    xmlrpc_parse_value(env, param, "({s:s,s:s,s:s,*})",  
+        "user", &user,  
+        "domain", &domain,  
+        "password", &password  
+    );
+    
+    if (env->fault_occurred) {  
+        return NULL;  
+    }
+    
+    rs = vpasswd(user, domain, password, 0) == 0 ? 1 : 0;
+    
+    return xmlrpc_build_value(env, "b", rs);  
+}
+
+static xmlrpc_value *vpop_setquota(xmlrpc_env *env, xmlrpc_value *param, void *data)  
+{  
+    char *user, *domain, *quota;  
+    xmlrpc_bool rs;
+    
+    xmlrpc_parse_value(env, param, "({s:s,s:s,s:s,*})",  
+        "user", &user,  
+        "domain", &domain,  
+        "quota", &quota  
+    );
+    
+    if (env->fault_occurred) {  
+        return NULL;  
+    }
+    
+    rs = vsetuserquota(user, domain, quota) == 0 ? 1 : 0;
+    
+    return xmlrpc_build_value(env, "b", rs);  
+}
+
+int main(int argc, char **argv)  
+{  
+    xmlrpc_cgi_init(XMLRPC_CGI_NO_FLAGS);
+    
+    xmlrpc_cgi_add_method_w_doc("vpop.adduser", &vpop_adduser, NULL,  
+    "b:S", "Add a vpopmail user to a domain with password, fullname and quota.");  
+    xmlrpc_cgi_add_method_w_doc("vpop.deluser", &vpop_deluser, NULL,  
+    "b:S", "Delete a user from a domain.");  
+    xmlrpc_cgi_add_method_w_doc("vpop.passwd", &vpop_passwd, NULL,  
+    "b:S", "Change the password of a user in a domain.");  
+    xmlrpc_cgi_add_method_w_doc("vpop.setquota", &vpop_setquota, NULL,  
+    "b:S", "Set the quota of a user in a domain.");
+    
+    xmlrpc_cgi_process_call();
+    
+    xmlrpc_cgi_cleanup();  
+    return 0;  
+}  
+```
+
diff --git a/_posts/2004-10-08-pearauth-and-vpop-xmlrpc.md b/_posts/2004-10-08-pearauth-and-vpop-xmlrpc.md
new file mode 100644 (file)
index 0000000..6ed30b0
--- /dev/null
@@ -0,0 +1,15 @@
+---
+title: PEAR::Auth and vpop-xmlrpc
+author: m6w6
+tags:
+- PHP
+---
+
+You guessed, I've written a [vpop-xmlrpc container](http://dev.iworks.at/vpop-xmlrpc/VPOPXMLRPC.phps) 
+for [PEAR::Auth](http://pear.php.net/package/Auth).
+
+There's also a [new version](http://dev.iworks.at/vpop-xmlrpc/vpop-xmlrpc-1.1.tar.gz) 
+of the vpop-xmlrpc cgi, which is needed for the Auth
+container, because the method **vpop.auth** has recently been added.
+
+Have fun ;)
diff --git a/_posts/2005-01-27-peclhttp.md b/_posts/2005-01-27-peclhttp.md
new file mode 100644 (file)
index 0000000..1d2d48e
--- /dev/null
@@ -0,0 +1,15 @@
+---
+title: pecl_http
+author: m6w6
+tags: 
+- PHP
+---
+
+I just released the new [http](http://pecl.php.net/package/pecl_http/) PECL
+package.
+
+It's named pecl_http because there's already an HTTP package in PEAR.  
+Hopefully channels will be available soon ;)
+
+There are for sure lots of bugs in it, but give it a try anyway... :)
+
diff --git a/_posts/2005-03-04-peclhttp-060.md b/_posts/2005-03-04-peclhttp-060.md
new file mode 100644 (file)
index 0000000..0d01aef
--- /dev/null
@@ -0,0 +1,15 @@
+---
+title: PECL::HTTP 0.6.0
+author: m6w6
+tags: 
+- PHP
+---
+
+I just released [pecl_http](http://pecl.php.net/package/pecl_http/) 0.6.0! ;)
+
+For its current capabilities you should have a look at
+[this](http://dev.iworks.at/ext-http/http-functions.html.gz) document.
+
+Don't hesitate to leave a comment, or drop [me](mailto:mike@php.net) a mail if
+you've got questions!
+
diff --git a/_posts/2005-06-05-moddomaintree.md b/_posts/2005-06-05-moddomaintree.md
new file mode 100644 (file)
index 0000000..21492ed
--- /dev/null
@@ -0,0 +1,70 @@
+---
+title: mod_domaintree
+author: m6w6
+tags: 
+- PHP
+---
+
+Friday evening I put together a tiny [Apache2](http://httpd.apache.org) module
+simliar to mod_vhost_alias or mod_vd.
+[mod_domaintree](http://cvs.iworks.at/co.php/mod_domaintree/mod_domaintree.c)
+maps host names to a filesystem tree. While mod_vhost_alias and mod_vd seem to
+be more flexible, they seem less useful to me.
+
+mod_vhost_alias lets you define very precisely which part of the host name
+maps to which directory but adds odd underscores if the part (number) of the
+hostname does not exist.
+
+mod_vd lets you define the numerical amount of host name parts to strip.
+
+But I **don't want to strip always** one part of the host name like "www" \- I
+just want to strip the first part of the host name (i.e. www) if it occurs in
+the sent hostname.
+
+If you want to try it out, there's nothing more to do then (w)getting
+[it](http://cvs.iworks.at/co.php/mod_domaintree/mod_domaintree.c?p=1) and
+running
+```shell
+sudo /usr/sbin/apxs2 -a -i -c mod_domaintree.c
+```
+## Sample Configuration:
+```apache
+DomainTreeEnabled On  
+DomainTreeMaxdepth 25  
+DomainTreeStripWWW On  
+DomainTreePrefix /sites  
+DomainTreeSuffix /html
+```
+
+### Mapped Hosts: (accepting "www" as prefix if DomainTreeStripWWW is enabled)
+
+  * company.co.at
+  * sub1.company.co.at
+  * sub2.company.co.at
+  * organisation.or.at
+  * example.at
+  * example.com
+
+### Resulting Filesystem Tree:
+```shell
+ /sites  
+    +- /at  
+    |    +- /co  
+    |    |    +- /company  
+    |    |        +- /html  
+    |    |        +- /sub1  
+    |    |        |    +- /html  
+    |    |        +- /sub2  
+    |    |            +- /html  
+    |    +- /or  
+    |    |    +- /organisation  
+    |    |        +- /html  
+    |    +- /example  
+    |        +- /html  
+    +- /com  
+        +- /example  
+            +- /html
+```
+
+PS: I was very suprised how easy it is to build a simple module for Apache (if
+you have some templates to look at though). :)
diff --git a/_posts/2005-06-07-httprequestpool-in-peclhttp.md b/_posts/2005-06-07-httprequestpool-in-peclhttp.md
new file mode 100644 (file)
index 0000000..b0c8523
--- /dev/null
@@ -0,0 +1,35 @@
+---
+title: HttpRequestPool in PECL::HTTP
+author: m6w6
+tags: 
+- PHP
+---
+
+I just checked in a first working version of HttpRequestPool into CVS.  
+It's curl_multi that's doing its job underneath and is used tp send several
+HttpRequests at once.
+```php  
+$urls = array(  
+    'http://www.php.net/',  
+    'http://pear.php.net/',  
+    'http://pecl.php.net/'  
+);  
+  
+$pool = new HttpRequestPool;  
+foreach ($urls as $url) {  
+    $pool->attach(new HttpRequest($url, HTTP_METH_HEAD));  
+}  
+  
+try {  
+    $pool->send();  
+    foreach ($pool as $r) {  
+        $status = $r->getResponseCode();  
+        printf("%-20s is %sn",  
+            $r->getUrl(),  
+            $status == 200 ? "ALIVE" : "NOT OK ($status)"  
+        );  
+    }  
+} catch (HttpException $ex) {  
+    echo $ex;  
+}  
+```
diff --git a/_posts/2005-06-29-is-php-staying-language-i-want-to-work-with.md b/_posts/2005-06-29-is-php-staying-language-i-want-to-work-with.md
new file mode 100644 (file)
index 0000000..c1a4e29
--- /dev/null
@@ -0,0 +1,17 @@
+---
+title: Is PHP staying the language I want to work with?
+author: m6w6
+tags: 
+- PHP
+---
+
+While some of the core PHP internals already see theirself that there's
+something wrong with the so-called generic way ZE2 looks up classes, many
+stolidly ignore the claims of PHP users...
+
+Look at this [MARC Thread](http://marc.info/?t=111887022700001&r=1&w=2) and that
+[MARC Thread](http://marc.info/?t=111999411200002&r=1&w=2).
+
+[Now something to laugh (or cry) at](http://marc.info/?l=pear-cvs&m=111999141214948&w=2)
+
+WTF?
diff --git a/_posts/2005-08-26-pecl-http-lap-12.md b/_posts/2005-08-26-pecl-http-lap-12.md
new file mode 100644 (file)
index 0000000..dcae7a7
--- /dev/null
@@ -0,0 +1,32 @@
+---
+title: PECL HTTP, lap 12
+author: m6w6
+tags: 
+- PHP
+---
+
+Today I released [PECLs HTTP extension version 0.12](http://pecl.php.net/package/pecl_http/0.12.0)
+
+A lot of work and fixes have gone into it, and I hope it's becoming stable
+even this century ;)
+
+Major changes are a general API cleanup where AuthBasic hooks have been
+removed and many HttpRequest methods have been sanitized.
+
+The HttpResponse class should now work with PHP5 as a webserver module as well
+and should not any longer have hard dependencies on ext/session and ext/zlib.
+
+Additionally, if you have libmhash (note: not necessarily ext/mhash) you can
+choose a hashing algorithm provided by libmhash to generate your ETags, which
+is done through the following INI setting: http.etag_mode = MHASH_SHA256
+(MHASH_SHA256 is an example and can be replaced by any MHASH constant **if**
+you have ext/mhash).
+
+The message and header parsers have been vastly improved to be able to parse
+(in principle invalid) messages and headers that only have a single LF instead
+of CRLF.
+
+And last but not least it should again flawlessly build for PHP4.
+
+So far, have fun and be sure to check it out! :)
+
diff --git a/_posts/2005-09-12-tutorial-kinda-for-peclhttp.md b/_posts/2005-09-12-tutorial-kinda-for-peclhttp.md
new file mode 100644 (file)
index 0000000..b8ea458
--- /dev/null
@@ -0,0 +1,360 @@
+---
+title: Tutorial -kinda- for pecl/http
+author: m6w6
+tags:
+- PHP
+---
+
+I've added a tiny tutorial, or sort of collection of usage examples,
+to the pecl/http repository.
+
+You can read it in the extended post, or just check it out from CVS.
+Please note that the code for the XMLRPC client has just been put into CVS.
+
+## GET Queries
+
+The HttpRequest class can be used to execute any HTTP request method.
+The following example shows a simple GET request where a few query
+parameters are supplied. Additionally potential cookies will be read
+from and written to a file.
+
+```php
+$r = new HttpRequest('http://www.google.com');
+
+// store Googles cookies in a dedicated file
+$r->setOptions(
+    array(    'cookiestore'    => '../cookies/google.txt',
+    )
+);
+
+$r->setQueryData(
+    array(    'q'     => '+"pecl_http" -msg -cvs -list',
+              'hl'    => 'de'
+    )
+);
+
+// HttpRequest::send() returns an HttpMessage object
+// of type HttpMessage::TYPE_RESPONSE or throws an exception
+try {
+    print $r->send()->getBody();
+} catch (HttpException $e) {
+    print $e;
+}
+```
+
+## Multipart Posts
+
+
+The following example shows an multipart POST request, with two form
+fields and an image that's supposed to be uploaded to the server.
+
+It's a bad habit as well as common practice to issue a redirect after
+an received POST request, so we'll allow a redirect by enabling the
+redirect option.
+
+```php
+$r = new HttpRequest('http://dev.iworks.at/.print_request.php',
+    HTTP_METH_POST);
+
+// if redirects is set to true, a single redirect is allowed;
+// one can set any reasonable count of allowed redirects
+$r->setOptions(
+    array(    'cookies'    => array('MyCookie' => 'has a value'),
+              'redirect'   => true,
+    )
+);
+
+// common form data
+$r->setPostFields(
+    array(    'name'    => 'Mike',
+              'mail'    => 'mike@php.net',
+    )
+);
+// add the file to post (form name, file name, file type)
+$r->addPostFile('image', 'profile.jpg', 'image/jpeg');
+
+try {
+    print $r->send()->getBody();
+} catch (HttpException $e) {
+    print $e;
+}
+```
+
+## Parallel Requests
+
+It's possible to execute several HttpRequests in parallel with the
+HttpRequestPool class.  HttpRequests to send, do not need to perform
+the same request method, but can only be attached to one HttpRequestPool
+at the same time.
+
+```php
+try {
+    $p = new HttpRequestPool;
+    // if you want to set _any_ options of the HttpRequest object,
+    // you need to do so *prior attaching* to the request pool!
+    $p->attach(new HttpRequest('http://pear.php.net',
+        HTTP_METH_HEAD));
+    $p->attach(new HttpRequest('http://pecl.php.net',
+        HTTP_METH_HEAD));
+} catch (HttpException $e) {
+    print $e;
+    exit;
+}
+
+try {
+    $p->send();
+    // HttpRequestPool implements an iterator
+    // over attached HttpRequest objects
+    foreach ($p as $r) {
+        echo "Checking ", $r->getUrl(), " reported ",
+            $r->getResponseCode(), "\n";
+    }
+} catch (HttpException $e) {
+    print $e;
+}
+```
+
+### Parallel Requests?
+
+You can use a more advanced approach by using the protected interface of
+the HttpRequestPool class.  This allows you to perform some other tasks
+while the requests are executed.
+
+```php
+class Pool extends HttpRequestPool
+{
+    public function __construct()
+    {
+        parent::__construct(
+            new HttpRequest('http://pear.php.net',
+                HTTP_METH_HEAD),
+            new HttpRequest('http://pecl.php.net',
+                HTTP_METH_HEAD)
+        );
+
+        // HttpRequestPool methods socketPerform() and
+        // socketSelect() are protected;  one could use
+        // this approach to do something else
+        // while the requests are being executed
+        print "Executing requests";
+        for ($i = 0; $this->socketPerform(); $i++) {
+            $i % 10 or print ".";
+            if (!$this->socketSelect()) {
+                throw new HttpException("Socket error!");
+            }
+        }
+        print "nDone!n";
+    }
+}
+
+try {
+    foreach (new Pool as $r) {
+        echo "Checking ", $r->getUrl(), " reported ",
+            $r->getResponseCode(), "\n";
+    }
+} catch (HttpException $ex) {
+    print $e;
+}
+```
+
+## Cached Responses
+
+One of the main key features of HttpResponse is HTTP caching.  HttpResponse
+will calculate an ETag based on the http.etag_mode INI setting as well as
+it will determine the last modification time of the sent entity.  It uses
+those two indicators to decide if the cache entry on the client side is
+still valid and will emit an &quot;304 Not Modified&quot; response if applicable.
+
+```php
+HttpResponse::setCacheControl('public');
+HttpResponse::setCache(true);
+HttpResponse::capture();
+
+print "This will be cached until content changes!\n";
+print "Note that this approach will only save the clients download time.\n";
+```
+
+## Bandwidth Throttling
+
+HttpResponse supports a basic throttling mechanism, which is enabled by
+setting a throttle delay and a buffer size.  PHP will sleep the specified
+amount of seconds after each sent chunk of specified bytes.
+
+```php
+// send 5000 bytes every 0.2 seconds, i.e. max ~25kByte/s
+HttpResponse::setThrottleDelay(0.2);
+HttpResponse::setBufferSize(5000);
+HttpResponse::setCache(true);
+HttpResponse::setContentType('application/x-zip');
+HttpResponse::setFile('../archive.zip');
+HttpResponse::send();
+```
+
+## KISS XMLRPC Client
+
+```php
+class XmlRpcClient
+{
+    public $namespace;
+    protected $request;
+
+    public function __construct($url, $namespace = '')
+    {
+        $this->namespace = $namespace;
+        $this->request = new HttpRequest($url, HTTP_METH_POST);
+        $this->request->setContentType('text/xml');
+    }
+
+    public function setOptions($options = array())
+    {
+        return $this->request->setOptions($options);
+    }
+
+    public function addOptions($options)
+    {
+        return $this->request->addOptions($options);
+    }
+
+    public function __call($method, $params)
+    {
+        if ($this->namespace) {
+            $method = $this->namespace .'.'. $method;
+        }
+        $this->request->setRawPostData(
+            xmlrpc_encode_request($method, $params));
+        $response = $this->request->send();
+        if ($response->getResponseCode() != 200) {
+            throw new Exception($response->getBody(),
+                $response->getResponseCode());
+        }
+        return xmlrpc_decode($response->getBody(), 'utf-8');
+    }
+
+    public function getHistory()
+    {
+        return $this->request->getHistory();
+    }
+}
+```
+
+## Simple Feed Aggregator
+
+```php
+class FeedAggregator
+{
+    public $directory;
+    protected $feeds = array();
+
+    public function __construct($directory = 'feeds')
+    {
+        $this->setDirectory($directory);
+    }
+
+    public function setDirectory($directory)
+    {
+        $this->directory = $directory;
+        foreach (glob($this->directory .'/*.xml') as $feed) {
+            $this->feeds[basename($feed, '.xml')] = filemtime($feed);
+        }
+    }
+
+    public function url2name($url)
+    {
+        return preg_replace('/[^w.-]+/', '_', $url);
+    }
+
+    public function hasFeed($url)
+    {
+        return isset($this->feeds[$this->url2name($url)]);
+    }
+
+    public function addFeed($url)
+    {
+        $r = $this->setupRequest($url);
+        $r->send();
+        $this->handleResponse($r);
+    }
+
+    public function addFeeds($urls)
+    {
+        $pool = new HttpRequestPool;
+        foreach ($urls as $url) {
+            $pool->attach($r = $this->setupRequest($url));
+        }
+        $pool->send();
+
+        foreach ($pool as $request) {
+            $this->handleResponse($request);
+        }
+    }
+
+    public function getFeed($url)
+    {
+        $this->addFeed($url);
+        return $this->loadFeed($this->url2name($url));
+    }
+
+    public function getFeeds($urls)
+    {
+        $feeds = array();
+        $this->addFeeds($urls);
+        foreach ($urls as $url) {
+            $feeds[] = $this->loadFeed($this->url2name($url));
+        }
+        return $feeds;
+    }
+
+    protected function saveFeed($file, $contents)
+    {
+        if (file_put_contents($this->directory .'/'. $file .'.xml', $contents)) {
+            $this->feeds[$file] = time();
+        } else {
+            throw new Exception(
+                "Could not save feed contents to $file.xml");
+        }
+    }
+
+    protected function loadFeed($file)
+    {
+        if (isset($this->feeds[$file])) {
+            if ($data = file_get_contents($this->directory .'/'. $file .'.xml')) {
+                return $data;
+            } else {
+                throw new Exception(
+                    "Could not load feed contents from $file.xml");
+            }
+        } else {
+            throw new Exception("Unknown feed/file $file.xml");
+        }
+    }
+
+    protected function setupRequest($url)
+    {
+        $r = new HttpRequest($url);
+        $r->setOptions(array('redirect' => true));
+
+        $file = $this->url2name($url);
+
+        if (isset($this->feeds[$file])) {
+            $r->setOptions(array('lastmodified' => $this->feeds[$file]));
+        }
+
+        return $r;
+    }
+
+    protected function handleResponse(HttpRequest $r)
+    {
+        if ($r->getResponseCode() != 304) {
+            if ($r->getResponseCode() != 200) {
+                throw new Exception("Unexpected response code ".
+                    $r->getResponseCode());
+            }
+            if (!strlen($body = $r->getResponseBody())) {
+                throw new Exception("Received empty feed from ".
+                    $r->getUrl());
+            }
+            $this->saveFeed($this->url2name($r->getUrl()), $body);
+        }
+    }
+}
+```
diff --git a/_posts/2005-10-04-references-in-php.md b/_posts/2005-10-04-references-in-php.md
new file mode 100644 (file)
index 0000000..08b5135
--- /dev/null
@@ -0,0 +1,13 @@
+---
+title: References in PHP
+author: m6w6
+tags: 
+- PHP
+---
+
+Derick made his article about variable references - published in 
+[PHP Architect](http://www.phparch.com/)s June edition - 
+[available online](http://derickrethans.nl/php_references_article.php).
+
+If you ever wanted to know how variables and references in PHP **look like** ,
+this read is a MUST.
diff --git a/_posts/2005-11-13-obviously.md b/_posts/2005-11-13-obviously.md
new file mode 100644 (file)
index 0000000..3bf75fc
--- /dev/null
@@ -0,0 +1,8 @@
+---
+title: Obviously...
+author: m6w6
+tags: 
+- WTF
+---
+
+[...morons don't die off](http://bugs.php.net/bug.php?id=35208)
diff --git a/_posts/2005-11-13-php-51-around-the-corner.md b/_posts/2005-11-13-php-51-around-the-corner.md
new file mode 100644 (file)
index 0000000..1f7b917
--- /dev/null
@@ -0,0 +1,165 @@
+---
+title: PHP-5.1 around the corner
+author: m6w6
+tags: 
+- PHP
+---
+
+Here's a tidied up excerpt of the current NEWS file with all relevant changes
+since PHP 5.0, which may help on the decision to upgrade (even from PHP 4 :))
+
+###  Fixes
+
+  * More than 350
+
+###  Changes
+
+  * Changed PDO constants to class constants (PDO::CONST_NAME)
+  * Changed SQLite extension to be a shared module in Windows distribution
+  * Changed "instanceof" and "catch" operators, [is_a](http://php.net/is_a)() and [is_subclass_of](http://php.net/is_subclass_of)() functions to not call [__autoload](http://php.net/__autoload)()
+  * Changed [sha1_file](http://php.net/sha1_file)() and [md5_file](http://php.net/md5_file)() functions to use streams instead of low level IO
+  * Changed abstract private methods to be not allowed anymore
+  * Changed [stream_filter_(ap|pre)pend](http://php.net/stream_filter_append)() to return resource
+  * Changed mysqli_exception and sqlite_exception to use RuntimeException as base if SPL extension is present
+
+###  Extensions moved to [PECL](http://pecl.php.net)
+
+  * cpdf
+  * dio
+  * fam
+  * ingres_ii
+  * mcve
+  * mnogosearch
+  * oracle
+  * ovrimos
+  * pfpro
+  * w32api
+  * yp
+
+###  Upgraded [PEAR](http://pear.php.net)
+
+  * to channel-featuring v1.4###  Upgraded bundled libraries
+
+### Upgraded bundled libraries
+
+  * PCRE library to version 6.2
+  * SQLite 3 library in ext/pdo_sqlite to 3.2.7
+  * SQLite 2 library in ext/sqlite to 2.8.16###  Upgraded bundled libraries in Windows distribution
+
+### Upgraded bundled libraries in Windows distribution
+  * zlib 1.2.3
+  * curl 7.14.0
+  * openssl 0.9.8
+  * ming 0.3b
+  * libpq (PostgreSQL) 8.0.1
+
+###  Improvements and Additions
+
+  * Improved SPL extension  
+    * Moved RecursiveArrayIterator from examples into extension
+    * Moved RecursiveFilterIterator from examples into extension
+    * Added SplObjectStorage
+    * Made all SPL constants class constants
+    * Renamed CachingRecursiveIterator to RecursiveCachingIterator to follow Recursive<*>Iterator naming scheme
+  * Added support for class constants and static members for internal classes
+  * Added PDO::MYSQL_ATTR_USE_BUFFERED_QUERY parameter for pdo_mysql
+  * Added [date_timezone_set](http://php.net/date_timezone_set)() function to set the timezone that the date functions will use
+  * Added [pg_fetch_all_columns](http://php.net/pg_fetch_all_columns)() function to fetch all values of a column from a result cursor
+  * Added support for LOCK_EX flag for [file_put_contents](http://php.net/file_put_contents)()
+  * Implemented feature request [#33452](http://bugs.php.net/33452)
+  * Improved PHP extension loading mechanism with support for module dependencies and conflicts
+  * Allowed return by reference from internal functions
+  * Rewrote [strtotime](http://php.net/strtotime)() with support for timezones and many new formats. Implements feature requests [#21399](http://bugs.php.net/21399), [#26694](http://bugs.php.net/26694), [#28088](http://bugs.php.net/28088), [#29150](http://bugs.php.net/29150), [#29585](http://bugs.php.net/29585) and [#29595](http://bugs.php.net/29595)
+  * Added bindto socket context option
+  * Added offset parameter to the [stream_copy_to_stream](http://php.net/stream_copy_to_stream)() function
+  * Added offset & length parameters to [substr_count](http://php.net/substr_count)() function
+  * Removed [php_check_syntax](http://php.net/php_check_syntax)() function which never worked properly
+  * Removed garbage manager in Zend Engine which results in more aggressive freeing of data
+  * [Improved interactive mode of PHP CLI](http://blog.thinkphp.de/archives/44-More-PHP-power-on-the-command-line.html)
+  * Improved performance of:
+  * general execution/compilation
+  * [switch](http://php.net/switch)() statement
+  * several array functions
+  * virtual path handling by adding a [realpath](http://php.net/realpath)() cache
+  * variable fetches
+  * magic method invocations
+  * Improved support for embedded server in mysqli
+  * Improved mysqli extension
+  * added constructor for mysqli_stmt and mysqli_result classes
+  * added new function [mysqli_get_charset](http://php.net/mysqli_get_charset)()
+  * added new function [mysqli_set_charset](http://php.net/mysqli_set_charset)()
+  * added new class mysqli_driver
+  * added new class mysqli_warning
+  * added new class mysqli_execption 
+  * added new class mysqli_sql_exception
+  * Improved SPL extension
+  * added standard hierarchy of Exception classes
+  * added interface Countable
+  * added interfaces Subject and Observer
+  * added spl_autoload*() functions
+  * converted several 5.0 examples into c code
+  * added class FileObject
+  * added possibility to use a string with [class_parents](http://php.net/class_parents)() and [class_implements](http://php.net/class_implements)()
+  * Added man pages for "phpize" and "php-config" scripts
+  * Added support for .cc files in extensions
+  * Added PHP_INT_MAX and PHP_INT_SIZE as predefined constants
+  * Added user opcode API that allow overloading of opcode handlers
+  * Added an optional remove old session parameter to [session_regenerate_id](http://php.net/session_regenerate_id)()
+  * Added array type hinting
+  * Added the [tidy_get_opt_doc](http://php.net/tidy_get_opt_doc)() function to return documentation for configuration options in tidy
+  * Added support for .cc files in extensions
+  * Added [imageconvolution](http://php.net/imageconvolution)() function which can be used to apply a custom 3x3 matrix convolution to an image
+  * Added optional first parameter to XsltProcessor::registerPHPFunctions to only allow certain functions to be called from XSLT
+  * Added the ability to override the autotools executables used by the buildconf script via the PHP_AUTOCONF and PHP_AUTOHEADER environmental variables
+  * Added several new functions to support the PostgreSQL v3 protocol introduced in PostgreSQL 7.4
+  * [pg_transaction_status](http://php.net/pg_transaction_status)() - in-transaction status of a database connection
+  * [pg_query_params](http://php.net/pg_query_params)() - execution of parameterized queries
+  * [pg_prepare](http://php.net/pg_prepare)() - prepare named queries
+  * [pg_execute](http://php.net/pg_execute)() - execution of named prepared queries
+  * [pg_send_query_params](http://php.net/pg_send_query_params)() - async equivalent of [pg_query_params](http://php.net/pg_query_params)()
+  * [pg_send_prepare](http://php.net/pg_send_prepare)() - async equivalent of [pg_prepare](http://php.net/pg_prepare)()
+  * [pg_send_execute](http://php.net/pg_send_execute)() - async equivalent of [pg_execute](http://php.net/pg_execute)()
+  * [pg_result_error_field](http://php.net/pg_result_error_field)() - highly detailed error information, most importantly the SQLSTATE error code
+  * [pg_set_error_verbosity](http://php.net/pg_set_error_verbosity)() - set verbosity of errors
+  * Added optional fifth parameter "count" to [preg_replace_callback](http://php.net/preg_replace_callback)() and [preg_replace](http://php.net/preg_replace)() to count the number of replacements made. FR [#32275](http://bugs.php.net/32275)
+  * Added optional third parameter "charlist" to [str_word_count](http://php.net/str_word_count)() which contains characters to be considered as word part. FR [#31560](http://bugs.php.net/31560)
+  * Added interface Serializeable
+  * Added [pg_field_type_oid](http://php.net/pg_field_type_oid)() PostgreSQL function
+  * Added zend_declare_property_...() and zend_update_property_...() API functions for bool, double and binary safe strings
+  * Added possibility to access INI variables from within .ini file
+  * Added variable $_SERVER['REQUEST_TIME'] containing request start time
+  * Added optional float parameter to [gettimeofday](http://php.net/gettimeofday)()
+  * Added [apache_reset_timeout](http://php.net/apache_reset_timeout)() Apache1 function
+  * Added [sqlite_fetch_column_types](http://php.net/sqlite_fetch_column_types)() 3rd argument for arrays
+  * Added optional offset parameter to [stream_get_contents](http://php.net/stream_get_contents)() and [file_get_contents](http://php.net/file_get_contents)()
+  * Added optional maxlen parameter to [file_get_contents](http://php.net/file_get_contents)()
+  * Added SAPI hook to get the current request time
+  * Added new functions:
+  * [array_diff_key](http://php.net/array_diff_key)()
+  * [array_diff_ukey](http://php.net/array_diff_ukey)()
+  * [array_intersect_key](http://php.net/array_intersect_key)()
+  * [array_intersect_ukey](http://php.net/array_intersect_ukey)()
+  * [array_product](http://php.net/array_product)()
+  * DomDocumentFragment::[appendXML](http://php.net/appendXML)()
+  * [fputcsv](http://php.net/fputcsv)()
+  * [htmlspecialchars_decode](http://php.net/htmlspecialchars_decode)()
+  * [inet_pton](http://php.net/inet_pton)()
+  * [inet_ntop](http://php.net/inet_ntop)()
+  * mysqli::client_info property
+  * [posix_access](http://php.net/posix_access)()
+  * [posix_mknod](http://php.net/posix_mknod)()
+  * SimpleXMLElement::XPathNamespace()
+  * [stream_context_get_default](http://php.net/stream_context_get_default)()
+  * [stream_socket_enable_crypto](http://php.net/stream_socket_enable_crypto)()
+  * [stream_wrapper_unregister](http://php.net/stream_wrapper_unregister)()
+  * [stream_wrapper_restore](http://php.net/stream_wrapper_restore)()
+  * [stream_filter_remove](http://php.net/stream_filter_remove)()
+  * [time_sleep_until](http://php.net/time_sleep_until)()
+  * Added DomDocument::$recover property for parsing not well-formed XML Documents
+  * Added Cursor support for MySQL 5.0.x in mysqli
+  * Added proxy support to ftp wrapper via http
+  * Added MDTM support to ftp_url_stat
+  * Added zlib stream filter support
+  * Added bz2 stream filter support
+  * Added max_redirects context option that specifies how many HTTP redirects to follow
+  * Added support of parameter=>value arrays to [xsl_xsltprocessor_set_parameter](http://php.net/xsl_xsltprocessor_set_parameter)()
diff --git a/_posts/2005-11-16-submitting-bug-for-php.md b/_posts/2005-11-16-submitting-bug-for-php.md
new file mode 100644 (file)
index 0000000..b3f359e
--- /dev/null
@@ -0,0 +1,19 @@
+---
+title: Submitting a bug for PHP
+author: m6w6
+tags: 
+- PHP
+---
+
+There will surely be the time where you find a bug in PHP, but prior
+submitting half hearted bug report make sure you've accomplished the following
+things:
+
+  * [search the bug tracker](http://bugs.php.net/search.php) if the bug has already been subbmitted
+  * put together a short and behaviour reproducing script
+  * verify the behaviour with the **latest** version AKA [snap](http://snaps.php.net) of PHP
+  * if PHP crashes, [generate a backtrace](http://bugs.php.net/bugs-generating-backtrace.php)
+
+If you're in doubt, read [this](http://bugs.php.net/how-to-report.php) if you
+didn't already (which you shouldn't tell anyone by the way).
+
diff --git a/_posts/2005-11-16-submitting-patch-for-php.md b/_posts/2005-11-16-submitting-patch-for-php.md
new file mode 100644 (file)
index 0000000..119ec59
--- /dev/null
@@ -0,0 +1,25 @@
+---
+title: Submitting a patch for PHP
+author: m6w6
+tags: 
+- PHP
+---
+
+If you once have that odd feeling that something in PHP is missing and you're
+brave enough to write something up (a patch) that would change that situation
+in your eyes, don't expect such a submission will make it into old branches.
+
+Questions to include new features in PHP-4 or PHP-5.0 will most probably be
+declined (for a good reason), so the chance that the invested time is wasted
+time is rather high.
+
+If you still feel confident about your addition, write the patch against the
+CVS HEAD or at least 5.1 branch, but for PHP-5.1 which is 
+[around the corner](../../2005-11-13/php-51-around-the-corner/)
+the probability for acceptance of new features has decreased a lot (or rather
+completely).
+
+On the other hand, if your patch is trying to fix a
+[bug](http://bugs.php.net), don't hesitate to provide a patch for **every
+single** CVS branch ;)
+
diff --git a/_posts/2005-11-16-time-to-say-good-bye.md b/_posts/2005-11-16-time-to-say-good-bye.md
new file mode 100644 (file)
index 0000000..02502ea
--- /dev/null
@@ -0,0 +1,18 @@
+---
+title: Time to say Good Bye
+author: m6w6
+tags: 
+- PHP
+---
+
+Yeah, it may come suddenly, but it's time to say good bye to curly braces used
+as string indexing operator.
+
+PHP-5.1 will issue an E_STRICT error, and PHP-6 will probably don't know this
+syntax any more.
+
+I don't know why, but I've got some strange sentimental feelings :-) , maybe
+because I've never used those other brackets for string indexing...
+
+So, beloved, I already miss you! :'(
+
diff --git a/_posts/2005-11-17-boost-your-website-with-apc.md b/_posts/2005-11-17-boost-your-website-with-apc.md
new file mode 100644 (file)
index 0000000..5e2475c
--- /dev/null
@@ -0,0 +1,58 @@
+---
+title: Boost your Website with APC
+author: m6w6
+tags: 
+- PHP
+---
+
+Two weeks ago I plugged [APC](http://pecl.php.net/package/APC) onto my main
+customers site, and I'm really satisfied by it now. I already tried it some
+time ago, but back then it had some problems with PEARs Quickforms and
+similiar heavy OO code, but those problems are fixed for about 90% now, some
+8% can be easily fixed by reordering **require** statements and the like and
+finally the remaining ~2% are going to be fixed by Rasmus in the foreseeable
+future.
+
+Note that I'm using APC with Debians PHP-4.3.10 and Apache2 package, which
+proofs a lot IMO ;) and there shouldn't be much that hinders you from trying
+it too!
+
+Here's a very simple instruction to boost your PHP enabled webserver:
+```shell    
+~$ pear download pecl/apc  
+~$ tar xzf APC-3.0.8.tgz  
+~$ rm -f package.xml  
+~$ cd APC-3.0.8  
+~/APC-3.0.8$ /usr/bin/phpize  
+~/APC-3.0.8$ ./configure --with-php-config=/usr/bin/php-config   
+    --enable-apc --enable-apc-mmap  
+~/APC-3.0.8$ make all  
+~/APC-3.0.8$ sudo make install
+```
+
+APC is now installed somewhere in /usr/lib/php.
+
+Some lines to add to php.ini:
+```ini    
+extension=apc.so  
+  
+[apc]  
+apc.enabled = 1  
+apc.cache_by_default = 1  
+apc.shm_size = 32  
+apc.num_files_hint = 500  
+apc.mmap_file_mask = /tmp/apc.XXXXXX
+```
+
+If you want to cache only a certain virtual host, set apc.cache_by_default to
+0 in php.ini and add the respective php_admin_value to your `<VirtualHost>`
+directive for the vhost.
+
+The package also contains a useful status script, just copy the shipped
+apc.php to your document root. You'll see how the usage of the SHM segment
+grows by time, and after some time you'll also see what settings to use for
+apc.num_files_hint and apc.shm_size when the whole site is cached.
+
+Sean recently added some [APC docs](http://docs.php.net/apc), too!
+
+Quod est demonstrandum, Website boosted! ;)
diff --git a/_posts/2005-12-06-hash-extension.md b/_posts/2005-12-06-hash-extension.md
new file mode 100644 (file)
index 0000000..3147fc2
--- /dev/null
@@ -0,0 +1,40 @@
+---
+title: Hash Extension
+author: m6w6
+tags: 
+- PHP
+---
+
+If you didn't notice yet, there's a new, seemingly unimpressive, nevertheless
+very useful, extension on the horizon, namely
+ext/[hash](http://pecl.php.net/package/hash).
+
+The initial version, proposed by Sara and Stefan -and it seems that Rasmus had
+his hands on it too- already featured the most common algorithms, and it has
+recently been extended to support now fairly every algo which libmhash
+provides.
+
+There's not been any public release yet, which means you'd need to build from
+CVS. [pecl4win](http://pecl4win.php.net) though, already provides fresh
+modules for Windows users.
+
+### It's usage is simple and intuitive
+Hashing a string:
+```php  
+echo hash('sha384', 'The quick brown fox jumps over the lazy dog');  
+```  
+Hashing a file:
+```php
+echo hash_file('md5', 'release-1.0.tgz');  
+```
+There's also an incremental interface available.
+
+The recently released version of the [HTTP
+extension](http://pecl.php.net/package/pecl_http) now uses the HASH extension
+instead of libmhash for generating its etag hashes.
+
+## Update:
+Just in case you missed, Sara released
+[pecl/hash](http://pecl.php.net/package/hash) today.  
+Check it out -- It'll be bundled with PHP-5.1.2!
+
diff --git a/_posts/2005-12-06-peclhttp-nasty-bug-and-new-example.md b/_posts/2005-12-06-peclhttp-nasty-bug-and-new-example.md
new file mode 100644 (file)
index 0000000..b6ac632
--- /dev/null
@@ -0,0 +1,147 @@
+---
+title: PECL::HTTP - A nasty bug and a new example
+author: m6w6
+tags: 
+- PHP
+---
+
+I just fixed a nasty bug which caused GZIP encoded files (speak tgz etc.) to
+be decoded. While it'll just eat **some** memory on a 200 response (besides
+that the body is not what one would expect), it'll eat all memory on 206
+(partial content) responses because the part is fed through zlib. I'll just
+need to revisit the HTTP RFC to check if checking for the "Vary" response
+header is the best bet before I drop the new release.
+
+Ok, that's it about the bad news -- I also added a new example to the tutorial
+which shows how one could efficiently download big files. Using the example
+code would look like:
+
+```php  
+$bigget = BigGet::url('http://example.com/big_file.bin');  
+$bigGet->saveTo('big_file.bin');  
+
+class BigGetRequest extends HttpRequest  
+{  
+    public $id;  
+}  
+  
+class BigGet extends HttpRequestPool  
+{  
+    const SIZE = 1048576;  
+  
+    private $url;  
+    private $size;  
+    private $count = 0;  
+    private $files = array();  
+  
+    static function url($url)  
+    {  
+        $head = new HttpRequest($url, HttpRequest::METH_HEAD);  
+        $headers = $head->send()->getHeaders();  
+        $head = null;  
+  
+        if (!isset($headers['Accept-Ranges'])) {  
+            throw new HttpExcpetion("Did not receive an ".  
+                "Accept-Ranges header from HEAD $url");  
+        }  
+        if (!isset($headers['Content-Length'])) {  
+            throw new HttpException("Did not receive a ".  
+                "Content-Length header from HEAD $url");  
+        }  
+  
+        $bigget = new Bigget;  
+        $bigget->url = $url;  
+        $bigget->size = $headers['Content-Length'];  
+        return $bigget;  
+    }  
+  
+    function saveTo($file)  
+    {  
+        $this->send();  
+        if ($w = fopen($file, 'wb')) {  
+            echo "nCopying temp files to $file ...n";  
+            foreach (glob("bigget_????.tmp") as $tmp) {  
+                echo "t$tmpn";  
+                if ($r = fopen($tmp, 'rb')) {  
+                    stream_copy_to_stream($r, $w);  
+                    fclose($r);  
+                }  
+                unlink($tmp);  
+            }  
+            fclose($w);  
+            echo "nDone.n";  
+        }  
+    }  
+  
+    function send()  
+    {  
+        // use max 3 simultanous requests with a req size of 1MiB  
+        while ($this->count < 3 &&  
+                -1 != $offset = $this->getRangeOffset()) {  
+            $this->attachNew($offset);  
+        }  
+  
+        while ($this->socketPerform()) {  
+            if (!$this->socketSelect()) {  
+                throw new HttpSocketException;  
+            }  
+        }  
+    }  
+  
+    private function attachNew($offset)  
+    {  
+        $stop = min($this->count * self::SIZE + self::SIZE,  
+            $this->size) - 1;  
+  
+        echo "Attaching new request to get range: $offset-$stopn";  
+  
+        $req = new BigGetRequest(  
+            $this->url,  
+            HttpRequest::METH_GET,  
+            array(  
+                'headers' => array(  
+                    'Range' => "bytes=$offset-$stop"  
+                )  
+            )  
+        );  
+        $this->attach($req);  
+        $req->id = $this->count++;  
+    }  
+  
+    private function getRangeOffset()  
+    {  
+        return ($this->size >=  
+            $start = $this->count * self::SIZE) ? $start : -1;  
+    }  
+  
+    protected function socketPerform()  
+    {  
+        try {  
+            $rc = parent::socketPerform();  
+        } catch (HttpRequestPoolException $x) {  
+            foreach ($x->exceptionStack as $e) {  
+                echo $e->getMessage(), "n";  
+            }  
+        }  
+  
+        foreach ($this->getFinishedRequests() as $r) {  
+            $this->detach($r);  
+  
+            if (206 != $rc = $r->getResponseCode()) {  
+                throw new HttpException(  
+                    "Unexpected response code: $rc");  
+            }  
+  
+            file_put_contents(  
+                sprintf("bigget_%04d.tmp", $r->id),  
+                $r->getResponseBody());  
+  
+            if (-1 != $offset = $this->getRangeOffset()) {  
+                $this->attachNew($offset);  
+            }  
+        }  
+  
+        return $rc;  
+    }  
+}
+```
diff --git a/_posts/2005-12-15-peclhttp-0200-outta-door.md b/_posts/2005-12-15-peclhttp-0200-outta-door.md
new file mode 100644 (file)
index 0000000..fca969b
--- /dev/null
@@ -0,0 +1,35 @@
+---
+title: PECL::HTTP 0.20.0 outta door
+author: m6w6
+tags: 
+- PHP
+---
+
+Version 0.20.0 of [pecl/http](http://pecl.php.net/package/pecl_http) has been
+released!  
+This is considered the most stable and friggin best release so far ;) so
+you're really encouraged to upgrade.
+
+### Release notes follow:
+
+* Request functionality requires libcurl >= 7.12.3 now  
++ Added 'bodyonly' request option  
++ Added IOCTL callback for cURL  
++  Added ssl_engines array and cookies array to the request info array  
++ Added http_parse_cookie() to parse Set-Cookie headers  
+- Renamed http_connectcode to connect_code in the request info array  
+- Enable "original headers" previously stripped off by the  
+  message parser:  
+    o X-Original-Transfer-Encoding (Transfer-Encoding)  
+    o X-Original-Content-Encoding (Content-Encoding)  
+    o X-Original-Content-Length (Content-Length)  
+- RequestExceptions thrown by HttpRequestPool::__construct() and  
+  send() are now wrapped into the HttpRequestPoolException  
+  object's $exceptionStack property  
+- Removed http_compress() and http_uncompress()  
+  (http_deflate/inflate ambiguity)  
+* Fixed bug which caused GZIP encoded archives to be decoded  
+* Fixed bug with DEFLATE encoded response messages  
+* Fixed several memory leaks and inconspicuous access violations  
+* Fixed some logical errors in the uri builder
+
diff --git a/_posts/2005-12-30-sfluentdecorated.md b/_posts/2005-12-30-sfluentdecorated.md
new file mode 100644 (file)
index 0000000..fdb91cb
--- /dev/null
@@ -0,0 +1,45 @@
+---
+title: s/fluent/decorated/
+author: m6w6
+tags: 
+- PHP
+---
+
+I've [read](http://www.achievo.org/blog/archives/25-The-danger-of-Fluent-interfaces.html) 
+[some](http://andigutmans.blogspot.com/2005/12/fluent-interfaces.html) 
+[posts](http://paul-m-jones.com/blog/?p=188) about "fluent interfaces" and 
+I have to agree that it's a bad idea to sacrifice a reasonable
+API to be able to write english code.
+
+It's anyway possible to accomplish that to some extent on a need-by-need basis
+with a class of only 20 lines of code:
+
+```php  
+class ReturnThisDecorator  
+{  
+    private $object;  
+    public $result;  
+  
+    function __construct($object)  
+    {  
+        if (is_object($object)) {  
+            $this->object = $object;  
+        } else {  
+            throw new InvalidArgumentException(  
+                "Expected an object as argument"  
+            );  
+        }  
+    }  
+  
+    function __call($method, $params)  
+    {  
+        $this->result = call_user_func_array(  
+            array($this->object, $method), $params  
+        );  
+        return $this;  
+    }  
+}  
+  
+$sms = new ReturnThisDecorator(new SMS);  
+echo $sms->from('...')->to('...')->message('...')->send()->result;  
+```
diff --git a/_posts/2006-01-27-apache2-moddomaintree-version-13.md b/_posts/2006-01-27-apache2-moddomaintree-version-13.md
new file mode 100644 (file)
index 0000000..57b6c4d
--- /dev/null
@@ -0,0 +1,22 @@
+---
+title: Apache2 mod_domaintree version 1.3
+author: m6w6
+tags: 
+- PHP 
+- WEB
+---
+
+I just released
+[mod_domaintree](http://freshmeat.net/projects/mod_domaintree/)-1.3 on
+[freshmeat](http://freahmeat.net).
+
+It'll take some time to appear, though.
+
+The code has been cleaned up a lot and a host name to directory cache (per
+server/process) has been added.
+
+Enable the cache by setting DomainTreeCache to a reasonable high number, like
+the amount of different domains being hosted.
+
+Drop me a [mail](mailto:mike@iworks.at) if you like it! ;)
+
diff --git a/_posts/2006-01-27-imapsavebody.md b/_posts/2006-01-27-imapsavebody.md
new file mode 100644 (file)
index 0000000..c25a175
--- /dev/null
@@ -0,0 +1,14 @@
+---
+title: imap_savebody()
+author: m6w6
+tags: 
+- PHP
+---
+
+If you -like me- were suffering from being unable to load big attachments
+through ext/imap because of PHPs memory limit, the new imap_savebody()
+function should be what you were looking for. It adds the ability to save any
+section (full mail, too) of a mail message to a file or stream.
+
+Adding it implied a non-trivial change to ext/imap, so if you encounter any
+new problems -with f.e. imap_fetchbody()- speak up ASAP, please! ;)
diff --git a/_posts/2006-02-03-some-cool-new-features-of-peclhttp.md b/_posts/2006-02-03-some-cool-new-features-of-peclhttp.md
new file mode 100644 (file)
index 0000000..71d3e09
--- /dev/null
@@ -0,0 +1,32 @@
+---
+title: Some cool new features of pecl/http
+author: m6w6
+tags: 
+- PHP
+---
+
+[PECL::HTTP](http://pecl.php.net/package/pecl_http) version 0.22 has been
+released this morning, and I want to point at some features which have been
+added to the extension since I last blogged about it.
+
+Incremental zlib (de)compressors were added in form of two classes,
+[HttpDeflateStream](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpDeflateStream) and
+[HttpInflateStream](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpInflateStream). I hope the names say it all ;)
+
+Another class, that might seem a bit odd at a quick glance, is
+[HttpQueryString](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpQueryString). It's a great tool to realize "paging" or
+sites with lots of rewrite rules AKA "pretty urls".
+
+The class [HttpMessage](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpMessage) has finally got its iterator interface to move
+up the message chain in a more convenient way. Messages can now be
+[detached](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpMessage_detach) and
+[prepended](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpMessage_prepend) from/to the message chain.
+
+Thanks to [Ilia](http://ilia.ws) you can now retrieve the raw request and
+response messages sent resp. received by an
+[HttpRequest](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpRequest) instance.
+
+The function [http_build_url](http://dev.iworks.at/ext-http/http-functions.html.gz#http_build_url) is now the most versatile and powerful
+utility to handle URLs (sorry for the lack of docs). Please [tell
+me](mailto:mike@iworks.at) if you don't think so ;)
+
diff --git a/_posts/2006-02-15-peclhttp-update.md b/_posts/2006-02-15-peclhttp-update.md
new file mode 100644 (file)
index 0000000..b28cb23
--- /dev/null
@@ -0,0 +1,142 @@
+---
+title: pecl/http update
+author: m6w6
+tags: 
+- PHP
+---
+
+Yeah, you guessed, version 0.23 of
+[pecl/http](http://pecl.php.net/package/pecl_http) has been released, and it's
+time for a feature update ;)
+
+###  Cookies
+
+[http_parse_cookie](http://dev.iworks.at/ext-http/http-functions.html.gz#http_parse_cookie)() has been reimplemented (and
+HttpRequest::getResponseCookie() has been moved to
+[HttpRequest::getResponseCookies](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpRequest_getResponseCookies)(). 
+After revisiting the
+original Netscape [draft](http://wp.netscape.com/newsref/std/cookie_spec.html)
+and the two [cookie](ftp://ftp.rfc-editor.org/in-notes/rfc2109.txt)
+[RFCs](ftp://ftp.rfc-editor.org/in-notes/rfc2965.txt) it was pretty obvious
+that the previous implementation was pretty bogus.
+
+Now it works as follows:
+
+```php  
+http_parse_cookie("cookie1=value; cookie2=\"1;2;3;4\"; path=/");  
+/*  
+stdClass Object  
+(  
+    [cookies] => Array  
+        (  
+            [cookie1] => value  
+            [cookie2] => 1;2;3;4  
+        )  
+  
+    [extras] => Array  
+        (  
+        )  
+  
+    [flags] => 0  
+    [expires] => 0  
+    [path] => /  
+    [domain] =>  
+)  
+*/  
+```
+
+As you can see, a cookie line can have several name/value pairs. The standard
+additional fields like expires, path etc. are recogniced automatically. The
+RFCs, though, define some other standard extra elements, here's where the
+third parameter of http_parse_cookie() plays in:
+
+```php
+http_parse_cookie("cookie1=value; cookie2=\"1;2;3;4\"; comment=\"none\"; path=/",  
+    0, array("comment"));  
+/*  
+stdClass Object  
+(  
+    [cookies] => Array  
+        (  
+            [cookie1] => value  
+            [cookie2] => 1;2;3;4  
+        )  
+  
+    [extras] => Array  
+        (  
+            [comment] => none  
+        )  
+  
+    [flags] => 0  
+    [expires] => 0  
+    [path] => /  
+    [domain] =>  
+)  
+*/
+```
+
+If "comment" wouldn't have been specified as an allowed extra element, it
+would just have been recognized as another cookie.  
+IF you pass HTTP_COOKIE_PARSE_RAW as second parameter to http_parse_cookie(),
+no urldecoding is performed.  
+The flags in the return value is a bitmask of HTTP_COOKIE_SECURE and
+HTTP_COOKIE_HTTPONLY.
+
+###  Messages
+
+Some users pointed me to the fact that neither
+[HttpMessage](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpMessage) 
+nor [HttpRequest](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpRequest) 
+provide accessors to the HTTP
+response reason phrase AKA status text. They've been added in form of
+[HttpMessage::getResponseStatus](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpMessage_getResponseStatus)() and
+[HttpRequest::getResponseStatus](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpRequest_getResponseStatus)().
+
+Some might have wondered why [HttpMessage](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpMessage)s are 
+chained in kind of a reverse order. Well, that has internal reasons, caused by how we retreive the data from
+[libcurl](http://curl.haxx.se) and how the message parser works. Anyway
+there's now [HttpMessage::reverse](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpMessage_reverse)() 
+which reorders the messages in a more intuitive chronical way:
+
+```php
+$msg = new HttpMessage(  
+"GET / HTTP/1.1  
+HTTP/1.1 302 Found  
+Location: /foo  
+GET /foo HTTP/1.1  
+HTTP/1.1 200 Ok");  
+foreach ($msg as $m) echo $m;  
+foreach ($msg->reverse() as $m) echo $m;  
+/*  
+HTTP/1.1 200 Ok  
+GET /foo HTTP/1.1  
+HTTP/1.1 302 Found  
+Location: /foo  
+GET / HTTP/1.1  
+  
+GET / HTTP/1.1  
+HTTP/1.1 302 Found  
+Location: /foo  
+GET /foo HTTP/1.1  
+HTTP/1.1 200 Ok  
+*/  
+```
+
+Note, though, that [HttpMessage::toString](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpMessage_toString)(true) automatically prepends parent
+messages, i.e. gives the latter result.
+
+###  Requests
+
+For servers that don't urldecode cookies, a new option has been added, named
+"encodecookies", which omits urlencoding cookies if set to FALSE.
+
+Similarily to the "lastmodified" request option, there's now an "etag" option
+working along the same lines.
+
+[HttpRequest::getHistory](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpRequest_getHistory)() 
+now returns a real HttpMessage property, which measn that this message chain is no longer immutable to
+changes made by the user.
+
+If a request fails for some reason, you should now be able to get the error
+message through [HttpRequest::getResponseInfo](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpRequest_getResponseInfo)("error").
+
diff --git a/_posts/2006-03-07-end-of-youth.md b/_posts/2006-03-07-end-of-youth.md
new file mode 100644 (file)
index 0000000..57c27d3
--- /dev/null
@@ -0,0 +1,16 @@
+---
+title: End of Youth
+author: m6w6
+tags: 
+- PHP
+---
+
+After more than a year of development and bulldozing the pecl-cvs mailing
+list, I'm ready to move [pecl/http](http://pecl.php.net/package/pecl_http)
+into 1.0-RC stage.
+
+Version 0.25 has just been released and I'm confident that we'll see a stable
+1.0 release not later than April.
+
+Thanks for your condolescence and patience in the last few months :)
+
diff --git a/_posts/2006-05-22-cookie-handling.md b/_posts/2006-05-22-cookie-handling.md
new file mode 100644 (file)
index 0000000..6dfb21d
--- /dev/null
@@ -0,0 +1,50 @@
+---
+title: Cookie Handling
+author: m6w6
+tags: 
+- PHP
+---
+
+I noticed some _weirdance_ about how libcurl and thus pecl/http handles
+cookies.
+
+I had to implement some changes which are only in CVS for now and which I'm
+going to outline here:
+
+```php  
+$r = new HttpRequest("http://www.google.at/");  
+$r->recordHistory = true;  
+// we don't care about cookies by default  
+// enable automatic recognition of cookies  
+$r->enableCookies();  
+$r->send();  
+// received cookies will be sent on the next request  
+$r->send();  
+// reset those "auto" cookies  
+// this needs at least libcurl >= v7.14.1  
+$r->resetCookies();  
+$r->send();  
+echo $r->getHistory()->toString(true);  
+```
+
+Beware that all this does not affect custom cookies set with
+[HttpRequest::setCookies](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpRequest_setCookies)() and
+[HttpRequest::addCookies](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpRequest_addCookies)(). 
+Custom cookies can always be unset by calling HttpRequest::setCookies().
+
+A final note on using the **cookiestore** option:
+
+```php
+$r = new HttpRequest("http://www.google.at/");  
+// load and save cookies from /tmp/cookies.txt  
+// if 'cookiesession' is TRUE, session cookies  
+// won't be loaded from the cookiestore  
+$r->setOptions(array(  
+    "cookiesession" => TRUE,  
+    "cookiestore" => "/tmp/cookies.txt")  
+);  
+$r->send();  
+```
+
+Note that using the cookiestore automatically enables libcurls cookie engine.
+
diff --git a/_posts/2006-05-31-konquerors-viewmode-buttons.md b/_posts/2006-05-31-konquerors-viewmode-buttons.md
new file mode 100644 (file)
index 0000000..b40d855
--- /dev/null
@@ -0,0 +1,19 @@
+---
+title: Konquerors ViewMode Buttons
+author: m6w6
+tags: 
+- WTF
+---
+
+If you, after upgrading to Dapper Drake, are missing your beloved ViewMode
+Buttons in Konqueror, locate
+`/usr/share/kubuntu-default-settings/kde-profile/default/share/apps/konqueror/konq-kubuntu.rc`
+and add the following ToolBar node:
+```xml    
+<ToolBar newline="false" hidden="false" name="viewModeToolBar" >  
+  <text>ViewMode Toolbar</text>  
+  <ActionList name="viewmode_toolbar" />  
+</ToolBar>
+```
+
+Yes, you guessed, this drove me mad ;)
diff --git a/_posts/2006-06-09-finally.md b/_posts/2006-06-09-finally.md
new file mode 100644 (file)
index 0000000..596c46b
--- /dev/null
@@ -0,0 +1,11 @@
+---
+title: Finally
+author: m6w6
+tags: 
+- PHP
+---
+
+I finally managed to release [pecl/http version 1.0.0](http://pecl.php.net/package/pecl_http/1.0.0).
+
+Happy HTTPing! ;)
+
diff --git a/_posts/2006-06-11-installing-peclhttp.md b/_posts/2006-06-11-installing-peclhttp.md
new file mode 100644 (file)
index 0000000..0d2a12a
--- /dev/null
@@ -0,0 +1,89 @@
+---
+title: Installing pecl_http
+author: m6w6
+tags: 
+- PHP
+---
+
+As [pecl/http](http://pecl.php.net/package/pecl_http) 1.0 has finally been
+released and I had noticed that it's been packaged already by several projects
+like PLD, Gentoo and FreeBSD, I wanted to explain what one is going to gain
+respectively lose by using the different build/configure options for the
+extension.  
+
+The help text of configure for pecl/http should look similar to the following:
+```
+  --enable-http           Enable extended HTTP support  
+  --with-http-curl-requests[=LIBCURLDIR]  
+                           HTTP: with cURL request support  
+  --with-http-zlib-compression[=LIBZDIR]  
+                           HTTP: with zlib encodings support  
+  --with-http-magic-mime[=LIBMAGICDIR]  
+                           HTTP: with magic mime response content type guessing  
+  --with-http-shared-deps  HTTP: disable to not depend on extensions like hash,  
+                                 iconv and session (when built shared)
+```
+
+If you link the extension source directory into your php tree, you should be
+aware that these options show up on the end of the list of configure options
+for **extensions** , not--as probably expected--in alphabetical order. This is
+due to a recent change to use config9.m4 because the HTTP extension may depend
+on several other PHP extensions ([hash](http://php.net/hash),
+[iconv](http://php.net/iconv), [session](http://php.net/session)).
+
+
+--with-http-curl-requests
+: This configure option enables request functionality, uses
+[libcurl](http://curl.haxx.se/libcurl/) and is _highly recommended_ to be
+enabled. The minumum libcurl version required is 7.12.3. Debian/stable
+currently ships 7.13.2 (no, this is not a typo).
+
+--with-http-zlib-compression
+: I think this is the most overseen/ignored option. Besides handling of
+compressed HTTP messages, it also provides superior deflate/inflate
+functionaly in regards to stability and performance compared to the standard
+zlib extension. Both [http_deflate](http://dev.iworks.at/ext-http/http-functions.html.gz#http_deflate)()
+/[http_inflate](http://dev.iworks.at/ext-http/http-functions.html.gz#http_inflate)() functions and
+http.deflate/http.inflate stream filters are able to encode/decode all valid
+gzip, zlib (AKA deflate) and raw deflated data. It requires at lieast libz
+version 1.2.0.4, while Debian/stable ships 1.2.2, and is also _highly recommended_ to be enabled.
+
+  
+
+--with-http-magic-mime
+: This option enables content type guessing for the
+[HttpResponse](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpResponse) 
+and [HttpMessage](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpMessage) 
+classes. It's rather a gimmick and
+thus not enabled by default. As there's no version information available for
+libmagic, I don't even know which is the minimum version required but I guess
+anything coming from a file-4.1x versioned package should work. If you get an
+empty string as content type for payload which is obviously XML text, check
+the magic.mime database you use for a broken **first** XML section. Comment
+out everything except the SVG detection as other XML types and HTML is handled
+further down the magic file (noticed on Debian systems). If you changed your
+magic.mime database, don't forget to regenerate the precompiled version with
+the `file -C` command.
+
+  
+
+--with-http-shared-deps
+: This option controls whether pecl/http will depend on extensions built as
+dynamically loadable modules. So, if e.g. ext/iconv has been compiled shared,
+pecl/http relies on ext/iconv to be loaded when itself is going to be loaded.
+This option is enabled by default.
+
+ * _ext/hash_  
+    pecl/http uses ext/hash to generate ETag hashes (else standard PHP MD5, SHA1 or CRC32).
+ * _ext/iconv_  
+    If ext/iconv is present, the [HttpQueryString](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpQueryString)  
+    class provides an [xlate](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpQueryString_xlate)() method for charset transformation.
+ * _ext/session_  
+    [http_redirect](http://dev.iworks.at/ext-http/http-functions.html.gz#http_redirect)() can   
+    automatically append session information to the redirect URL.
+ * _ext/spl_  
+    ext/spl cannot be built shared, so pecl/http always uses it if it's enabled.  
+    [HttpMessage](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpMessage) and 
+    [HttpRequestPool](http://dev.iworks.at/ext-http/http-functions.html.gz#HttpRequestPool) 
+    classes implement the interface Countable provided by ext/spl.
+
diff --git a/_posts/2006-08-18-round-up.md b/_posts/2006-08-18-round-up.md
new file mode 100644 (file)
index 0000000..1901bf9
--- /dev/null
@@ -0,0 +1,55 @@
+---
+title: Round up
+author: m6w6
+tags: 
+- PHP
+---
+
+It's been a long time since I wrote something here, mostly because I got
+distracted by some real private life recently ;) and due to paid work of
+course. Therefore I thought I'd round up what has happened behind the scenes
+in my PHP world.
+
+## PHP-6  
+I rewrote the output control layer for PHP-6 some months ago and I'm about to
+upgrade ext/zlib to see how it really works out.
+
+## PHP-5.2  
+I didn't contribute that much to this upcoming release. Two things I'd like to
+mention are a fix for the Apache2 SAPI where each header("Content-Type:
+aaa/bbb") caused Apache to add output filters for the type to the outgoing
+filter chain and the addition of the error_get_last() function, which is a
+convenient accessor to the last occured error without fiddling around with
+INI(track_errors) and $php_errormsg.
+
+
+## pecl/http  
+There's official [documentation](http://php.net/http) now available online in
+the PHP manual, yay! :) It's not fully fleshed out, but gives some feeling
+about the provided functionality and hints on how to use this module.
+
+[php|a](http://www.phparch.com/) published an article by me about pecl/http in
+their Augusts issue!
+
+There have also been three releases since 1.0, the most recent one (1.2)
+today. See the changes since then outlined below.
+
+### Improvements/Additions
+
+  * Improved response performance (HttpResponse, http_send API)
+  * Added http_build_cookie() function
+  * Added HttpQueryString::mod(array $params) method
+  * Added ArrayAccess to interfaces implemented by HttpQueryString
+  * Added HttpMessage::getHeader(string $name) method
+
+### Bug Fixes
+
+  * Fixed http_parse_cookie() allowed_extras and flags parameters
+  * Fixed configuration with shared dependencies
+  * Fixed endless loop in http_build_url("..")
+  * Fixed HttpResponse::capture() failure if buffered output exceeds 40k
+  * Fixed HttpQueryString failures with objects as params
+  * Fixed memory leaks with overloaded classes extending HTTP classes
+  * Fixed build with gcc-2.95 (Thanks to Alexander Zhuravlev)
+  * Fixed memory leak in inflate code (Thanks to Thomas Landro Johnsen)
+
diff --git a/_posts/2006-08-21-get-and-array-rumors.md b/_posts/2006-08-21-get-and-array-rumors.md
new file mode 100644 (file)
index 0000000..cd43046
--- /dev/null
@@ -0,0 +1,51 @@
+---
+title: __get() and array rumors
+author: m6w6 
+tags: 
+- PHP
+---
+
+There've been lots of rumors about overloaded array properties lately.
+
+The following code
+```php
+class funky {  
+  private $p = array();  
+  function __get($p) {  
+    return $this->p;  
+  }  
+}  
+$o = new funky;  
+$o->prop["key"] = 1;
+```
+
+will yield:
+
+```shell
+Notice: Indirect modification of overloaded property funky::$p has no effect
+```
+
+As arrays are the only complex types that are passed by value (resources don't
+really count here) the solution to described problem is simple: use an object;
+either an instance of stdClass or ArrayObject will do well, depending if you
+want to use array index notation.
+
+So the folloiwng code will work as expected, because the ArrayObject instance
+will pe passed by handle:
+
+```php  
+class smarty {  
+  private $p;  
+  function __construct() {  
+    $this->p = new ArrayObject;  
+  }  
+  function __get($p) {  
+    return $this->p;  
+  }  
+}  
+$o = new smarty;  
+$o->prop["key"] = 1;  
+```
+
+I guess most of you already knew, but anyway... ;)
+
diff --git a/_posts/2006-09-16-httprequestdatashare.md b/_posts/2006-09-16-httprequestdatashare.md
new file mode 100644 (file)
index 0000000..809ebf9
--- /dev/null
@@ -0,0 +1,151 @@
+---
+title: HttpRequestDataShare
+author: m6w6
+tags:
+- PHP
+---
+
+There are some news to talk about development of
+[pecl/http](http://pecl.php.net/package/pecl_http).
+
+I recently implemented an interface to the [curl-
+share](http://curl.haxx.se/libcurl/c/libcurl-share.html) functionality in form
+of an HttpRequestDataShare class.
+
+This is what [reflection](http://php.net/reflection) will tell you about it:
+
+```shell
+mike@honeybadger:~/build/php-5.2-debug$ cli --rc HttpRequestDataShare  
+Class [ <internal:http> class HttpRequestDataShare implements Countable ] {  
+  
+  - Constants [0] {  
+  }  
+  
+  - Static properties [1] {  
+    Property [ private static $instance ]  
+  }  
+  
+  - Static methods [1] {  
+    Method [ <internal> static public method singleton ] {  
+  
+      - Parameters [1] {  
+        Parameter #0 [ <optional> $global ]  
+      }  
+    }  
+  }  
+  
+  - Properties [4] {  
+    Property [ <default> public $cookie ]  
+    Property [ <default> public $dns ]  
+    Property [ <default> public $ssl ]  
+    Property [ <default> public $connect ]  
+  }  
+  
+  - Methods [5] {  
+    Method [ <internal, dtor> public method __destruct ] {  
+  
+      - Parameters [0] {  
+      }  
+    }  
+  
+    Method [ <internal, prototype Countable> public method count ] {  
+  
+      - Parameters [0] {  
+      }  
+    }  
+  
+    Method [ <internal> public method attach ] {  
+  
+      - Parameters [1] {  
+        Parameter #0 [ <required> HttpRequest $request ]  
+      }  
+    }  
+  
+    Method [ <internal> public method detach ] {  
+  
+      - Parameters [1] {  
+        Parameter #0 [ <required> HttpRequest $request ]  
+      }  
+    }  
+  
+    Method [ <internal> public method reset ] {  
+  
+      - Parameters [0] {  
+      }  
+    }  
+  }  
+}
+```
+
+Using this class, you can save a fair amount of time with name lookups which
+the following example shows:
+```php
+$s = HttpRequestDataShare::singleton(true);  
+print_r($s);  
+for ($i = 0; $i < 10; ++$i) {  
+    $r = new HttpRequest("http://www.google.com/");  
+    $s->attach($r);  
+    $r->send();  
+    printf("%0.6fn", $r->getResponseInfo("namelookup_time"));  
+    $s->detach($r);  
+}  
+```
+
+Executing this script without dns data sharing enabled gives the following
+results:
+```shell
+mike@honeybadger:~/build/php-5.2-debug$ cli  -d"http.request.datashare.dns=0"  
+    ~/devel/http_rshare.php  
+HttpRequestDataShare Object  
+(  
+    [cookie] =>  
+    [dns] =>  
+    [ssl] =>  
+    [connect] =>  
+)  
+0.071296  
+0.048798  
+0.049598  
+0.051545  
+0.046258  
+0.052318  
+0.043769  
+0.060753  
+0.049168  
+0.048568
+```
+
+...and with dns data sharing enabled:
+```shell
+mike@honeybadger:~/build/php-5.2-debug$ cli -d"http.request.datashare.dns=1"   
+    ~/devel/http_rshare.php  
+HttpRequestDataShare Object  
+(  
+    [cookie] =>  
+    [dns] => 1  
+    [ssl] =>  
+    [connect] =>  
+)  
+0.051945  
+0.000043  
+0.000041  
+0.000040  
+0.000039  
+0.000041  
+0.000041  
+0.000040  
+0.000040  
+0.000041
+```
+
+ **QED**
+
+You can either use a per-process global datashare object created with
+HttpRequestDataShare::singleton(true) or different instances for your
+HttpRequest objects. Note that dns datasharing is used autmagically for
+HttpRequestPool requests. Currently libcurl has implemented cookie and dns
+data sharing only, trying to enable ssl session or connect sharing will raise
+a warning.
+
+Be sure to try it out; either directly from CVS or the next release, probably
+being 1.3.0RC1.
diff --git a/_posts/2007-02-08-http-curl-and-stuff.md b/_posts/2007-02-08-http-curl-and-stuff.md
new file mode 100644 (file)
index 0000000..34085cd
--- /dev/null
@@ -0,0 +1,38 @@
+---
+title: HTTP, CURL and stuff
+author: m6w6
+tags: 
+- PHP
+---
+
+News, news, yawn.
+
+Daniel Stenberg, head of the [cURL](http://curl.haxx.se) project,
+[accepted](http://permalink.gmane.org/gmane.comp.web.curl.library/13439) a
+patch for sub second time out support within libcurl. That means that you can
+use float values as time outs with a millisecond resolution, as soon as you
+use libcurl >= v7.16.2, that is, a minimum supported time out of 0.001 seconds
+(which is **not** reasonable, just in case you wonder). On a side note, you
+should build libcurl with [c-ares](http://daniel.haxx.se/projects/c-ares/) to
+get working sub second DNS lookup time out support, AFAICT.
+
+Clay Loveless, usually [killing people softly with his random strings](http://killersoft.com/randomstrings/), 
+[mashing up APIs](http://mashery.com) or [providing compatibility libraries](http://code.google.com/p/phttp/), 
+kindly asked me, if there were persistent connection support in
+[pecl/http](http://pecl.php.net/package/pecl_http).
+
+> _Is there an option in pecl_http that I'm overlooking that would be the
+equivalent of STREAM_CLIENT_PERSISTENT?_
+
+I was already about to answer that libcurl already does that all for us,
+realizing that we destroy the used CURL handles at the end of each PHP request
+at the latest, thus killing any alive connections. This happened about two
+weeks ago, and pecl/http 1.5, of which RC1 had just been released, will
+support per process persistent CURL handles. It can be enabled at compile time
+only, as it's a quite intrusive feature. Yet I'm still unsure about the
+implementation of this feature and it might change in the future to become a
+bit more user-friendly.
+
+To use it, there's nothing else to be done than tossing --enable-http-
+persistent-handles at configure.
+
diff --git a/_posts/2007-02-10-something-i-didn-even-know-i-was-missing.md b/_posts/2007-02-10-something-i-didn-even-know-i-was-missing.md
new file mode 100644 (file)
index 0000000..6740a28
--- /dev/null
@@ -0,0 +1,12 @@
+---
+title: Something I didn't even know I was missing
+author: m6w6
+tags: 
+- PHP
+---
+```shell
+$ php --ri extension
+```
+
+Nice.
+
diff --git a/_posts/2007-04-01-upgrading-to-52.md b/_posts/2007-04-01-upgrading-to-52.md
new file mode 100644 (file)
index 0000000..24c6f76
--- /dev/null
@@ -0,0 +1,25 @@
+---
+title: Upgrading to 5.2
+author: m6w6
+tags: 
+- PHP
+---
+
+So I finally came around to upgrade to PHP 5.2 (I was running 4.4 on the
+production server until now). I know, what a shame! :)
+
+Anyway the only issue I really had, in spite testing the code really well over
+time, was with class_exists() and millions of warnings becaus of a missing
+__autoload(). I blame the people who introduced the second parameter to
+class_exists() **and** changing the default behaviour at the very same moment.
+Actually, it was an annoying but rather easy to fix compatibility brake.
+
+APC in conjunction with PHP-5.2 seems to work very well either, it even feels
+a lot less memory exhaustive than running APC+PHP-4.
+
+Ah yes, just on a side note, I also upgraded to Apache-2.2 in the same run.
+Somehow I now have a warm and fuzzy feeling running this up-to-date software,
+it really was already like a brinck in my stomach. Anyway, what's left is to
+migrate from the Apache module to the FastCGI SAPI and switching to the worker
+MPM... but I'm done already.
+
diff --git a/_posts/2007-05-03-apache-multiviews-are-evil.md b/_posts/2007-05-03-apache-multiviews-are-evil.md
new file mode 100644 (file)
index 0000000..63cb36f
--- /dev/null
@@ -0,0 +1,26 @@
+---
+title: Apache MultiViews are evil
+author: m6w6
+tags: 
+- WTF 
+- WEB
+---
+
+Suppose you've got a similar setup to:
+
+```apache
+RewriteEngine On  
+RewriteBase /  
+  
+RewriteCond %{REQUEST_FILENAME} -f [OR]  
+RewriteCond %{REQUEST_FILENAME} -d  
+RewriteRule .* - [QSA,L]  
+  
+RewriteRule ^network/?(w+)?$ network.php?path=$1
+```
+
+Apache will expand e.g. "network/foo/bar" to "network.php/foo/bar" which won't
+be expanded to "network.php?f=" because it --of course-- exists (RewriteCond -f).
+
+Evil! :)
+
diff --git a/_posts/2007-05-03-two-pitfalls-in-one-afternoon.md b/_posts/2007-05-03-two-pitfalls-in-one-afternoon.md
new file mode 100644 (file)
index 0000000..77cae90
--- /dev/null
@@ -0,0 +1,18 @@
+---
+title: Two pitfalls in one afternoon
+author: m6w6
+tags: 
+- WTF
+- WEB
+---
+
+This is not my day.
+
+&lt;quote url="<http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html>">  
+
+> words that are present in more than 50% of the rows are considered common and do not match
+
+&lt;/quote>
+
+RTFM! ;)
+
diff --git a/_posts/2007-05-09-phar-vs-world.md b/_posts/2007-05-09-phar-vs-world.md
new file mode 100644 (file)
index 0000000..5d8cb46
--- /dev/null
@@ -0,0 +1,30 @@
+---
+title: Phar vs World
+author: m6w6
+tags: 
+- WTF
+- PHP
+---
+
+Recent [discussions](http://marc.info/?t=117857313600047&r=1&w=2) about
+inclusion of [pecl/phar](http://pecl.php.net/package/phar) into the core
+distribution shows again that we are missing a defined process of handling
+additions to the PHP main distibution. How many people are really reading
+through all mails of 100+ message threads?
+
+It's going to be a chaos. Always. Once a developer has got his new, shiny and
+soon-to-be-world-dominating extension into the core, he'll be a even stronger
+advocator of the "no-new-extensions" camp. Not to disrespect any work, but
+this is pure rivalism, masculine--really!
+
+The idea of moving extensions from core to pecl is honorous, but we all know
+the current problems of this ideology.
+
+Many people have asked me when
+[pecl/http](http://pecl.php.net/package/pecl_http) will be included in the
+main distribution. My answer is short and simple: "Never" (I usually add a
+tiny sentence, but that's nothing encouraging either).
+
+Ah... and please do me a favour: rather keep your comments to yourself :)
+(...or toss it into the nonsense thread@internals).
+
diff --git a/_posts/2007-05-23-silence.md b/_posts/2007-05-23-silence.md
new file mode 100644 (file)
index 0000000..b71aa31
--- /dev/null
@@ -0,0 +1,75 @@
+---
+title: Silence
+author: m6w6
+tags: 
+- PHP
+---
+
+It's been [more than 3 months](http://blog.iworks.at/?/archives/50-HTTP,-CURL-and-stuff.html) 
+that I brought back to mind, what was happening in my PHP/HTTP/CURL world, so here we go.
+
+#### February:
+
+[pecl/http](http://pecl.php.net/package/pecl_http) with support for persistent
+handles has been released.
+
+A [proposal of mine at internals](http://marc.info/?l=php-dev&m=117188035610011&w=2) 
+to change the behaviour of read_property/write_property and get_property_ptr_ptr object handlers has
+successfully been ignored.
+
+The idea was the following:
+
+> Wouldn't it be reasonable for the engine to use get_property_ptr_ptr()
+whenever it wants to modify a property and get rid of using read_property()
+for write access?  
+> That would make rather simple ops like concatenation, in-/decrementation etc
+work again with overloaded internal classes. Just make the engine use
+read_property() followed by a write_property() when there's no
+get_property_ptr_ptr().
+
+
+Nobody was interested.
+
+#### March:
+
+I [added a comparison object handler](http://cvs.php.net/viewvc.cgi/php-src/ext/date/php_date.c?r1=1.131&r2=1.132&diff_format=u) 
+to the DateTime class, which means that comparisons of DateTime objects should work in recent
+PHP5 versions.
+
+I started development of pecl/libetpan, but [dropped it again](http://marc.info/?l=pecl-dev&m=117464452600994&w=2) 
+because of pretty huge differences between how the library works and how PHP is supposed to
+work. What a pity.
+
+A less fine guy, some Omid, wanted me to write a PHP extension which
+calculates the strength of "poker hands", but he jumped off when I had done
+the algos.
+
+#### April:
+
+A fine guy, pretending his name was Andreas Weber, noticed that pecl/http's
+request method implementation was completely b0rked. Thanks to his report it
+was fixed in 1.5.3.
+
+All fame Lukas Smith, queried me about what might have changed with my new
+output layer implementation for PHP6, but I noticed too late that it's been
+for a conference talk he was preparing, so I feel like I didn't spend enough
+attention to his questions. Sorry Lukas.
+
+I started to implement [libcurl's](http://curl.haxx.se) new multi_socket AKA
+hiper API in conjunction with [libevent](http://monkey.org/~provos/libevent/),
+but stumbled across a few
+[problem](http://curl.haxx.se/mail/lib-2007-04/0308.html)s.
+
+#### May:
+
+My journey with libcurl's multi_socket API
+[continues](http://curl.haxx.se/mail/lib-2007-05/0125.html), which eventually
+causes the delay of a first pecl/http 1.6 release candidate.
+
+I [tried](http://dev.iworks.at) [Drupal](http://drupal.org) for the first
+time.
+
+***
+
+Well, that'd be it. If it reads like an extrusion of junk, it probably was. ;)
+
diff --git a/_posts/2007-09-11-introducing-libcurls-multi-socket-api.md b/_posts/2007-09-11-introducing-libcurls-multi-socket-api.md
new file mode 100644 (file)
index 0000000..d0d414d
--- /dev/null
@@ -0,0 +1,96 @@
+---
+title: Introducing libcurls multi socket API
+author: m6w6
+tags: 
+- PHP
+---
+
+So, finally a first beta of [pecl_http](http://pecl.php.net/package/pecl_http)
+1.6 has been released.
+
+This is the first version which supports [libcurl](http://curl.haxx.se/libcurl/)s 
+[multi socketAPI](http://curl.haxx.se/libcurl/c/curl_multi_socket.html) introduced in 7.16
+through libevent.
+
+
+Here's a not very impressive comparison of the performance of the traditional
+multi API vs. the new multi socket API:
+```shell
+mike@honeybadger:~/build/php-5.2-debug$ cli   
+    ~/cvs/pecl/http/scripts/bench_select_vs_event.php   
+    -u http://honeybadger/empty.html  
+  
+>   1.134667s  
+  
+mike@honeybadger:~/build/php-5.2-debug$ cli   
+    ~/cvs/pecl/http/scripts/bench_select_vs_event.php   
+    -u http://honeybadger/empty.html  
+  
+>   1.151088s  
+  
+mike@honeybadger:~/build/php-5.2-debug$ cli   
+    ~/cvs/pecl/http/scripts/bench_select_vs_event.php   
+    -u http://honeybadger/empty.html  
+  
+>   1.131867s  
+  
+mike@honeybadger:~/build/php-5.2-debug$ cli   
+    ~/cvs/pecl/http/scripts/bench_select_vs_event.php   
+    -u http://honeybadger/empty.html -e  
+  
+>   0.993878s  
+  
+mike@honeybadger:~/build/php-5.2-debug$ cli   
+    ~/cvs/pecl/http/scripts/bench_select_vs_event.php   
+    -u http://honeybadger/empty.html -e  
+  
+>   0.998832s  
+  
+mike@honeybadger:~/build/php-5.2-debug$ cli   
+    ~/cvs/pecl/http/scripts/bench_select_vs_event.php   
+    -u http://honeybadger/empty.html -e  
+  
+>   0.997121s
+```
+
+Above empty.html is, well, empty. The following test requests a 100k file:
+```shell
+mike@honeybadger:~/build/php-5.2-debug$ cli    
+    ~/cvs/pecl/http/scripts/bench_select_vs_event.php    
+    -u http://honeybadger/100k.bin  
+  
+>   2.205190s  
+  
+mike@honeybadger:~/build/php-5.2-debug$ cli    
+    ~/cvs/pecl/http/scripts/bench_select_vs_event.php    
+    -u http://honeybadger/100k.bin  
+  
+>   2.210525s  
+  
+mike@honeybadger:~/build/php-5.2-debug$ cli    
+    ~/cvs/pecl/http/scripts/bench_select_vs_event.php    
+    -u http://honeybadger/100k.bin  
+  
+>   2.254281s  
+  
+mike@honeybadger:~/build/php-5.2-debug$ cli    
+    ~/cvs/pecl/http/scripts/bench_select_vs_event.php    
+    -u http://honeybadger/100k.bin -e  
+  
+>   2.007220s  
+  
+mike@honeybadger:~/build/php-5.2-debug$ cli    
+    ~/cvs/pecl/http/scripts/bench_select_vs_event.php    
+    -u http://honeybadger/100k.bin -e  
+  
+>   1.945564s  
+  
+mike@honeybadger:~/build/php-5.2-debug$ cli    
+    ~/cvs/pecl/http/scripts/bench_select_vs_event.php    
+    -u http://honeybadger/100k.bin -e  
+  
+>   1.969575s
+```
+
+So, apparently time savings are not huge, but noticable.
+
diff --git a/_posts/2008-11-18-qmail-spamassassin-selectivity.md b/_posts/2008-11-18-qmail-spamassassin-selectivity.md
new file mode 100644 (file)
index 0000000..2897cd7
--- /dev/null
@@ -0,0 +1,19 @@
+---
+title: Qmail + SpamAssassin + selectivity
+author: m6w6
+tags: 
+- SYS
+---
+
+Here's how my qmail-queue script looks like to selectively check messages with
+SpamAssassin for non-relay clients only:
+
+```sh
+#!/bin/sh  
+(if [ -n "${RELAYCLIENT+1}" -o `id -u` != 64011 ];   
+    then cat -;   
+    else /usr/bin/spamc -x -U /var/run/spamd/spamd.sock;   
+fi) | /usr/sbin/qmail-queue.orig
+```
+
+For the records.
diff --git a/_posts/2008-11-18-vpopmail-and-people-reaching-their-maildir-quota.md b/_posts/2008-11-18-vpopmail-and-people-reaching-their-maildir-quota.md
new file mode 100644 (file)
index 0000000..81e2e08
--- /dev/null
@@ -0,0 +1,58 @@
+---
+title: Vpopmail and people reaching their maildir quota
+author: m6w6
+tags: 
+- SYS
+---
+
+This tiny program lists all users of a domain with a maildir quota usage above
+90%.
+
+```c
+#include <stdio.h>  
+#include <stdlib.h>  
+#include <unistd.h>  
+#include <string.h>  
+  
+#include <pwd.h>  
+#include <errno.h>  
+  
+#include <vpopmail.h>  
+#include <vauth.h>  
+  
+int main(int argc, char **argv) {  
+    struct vqpasswd *user;  
+    char dir[1024];  
+    uid_t uid;  
+    gid_t gid;  
+    int offset_counter = -1, sort = 1, usage;  
+  
+    if (argc != 2) {  
+        fprintf(stderr, "Usage: %s <domain>n", argv[0]);  
+        return EXIT_FAILURE;  
+    }  
+    if (vget_assign(argv[1], NULL, 0, &uid, &gid) == NULL) {  
+        fprintf(stderr, "domain '%s' does not existn", argv[1]);  
+        return EXIT_FAILURE;  
+    }  
+    if (setgid(gid) || setuid(uid)) {  
+        fprintf(stderr, "could not setuid/setgid to %d:%dn", uid, gid);  
+        return EXIT_FAILURE;  
+    }  
+  
+    while (NULL != (user = vauth_getall(argv[1], !++offset_counter, sort))) {  
+        if (strcmp(user->pw_shell, "NOQUOTA")) {  
+            snprintf(dir, sizeof(dir), "%s/Maildir", user->pw_dir);  
+            usage = vmaildir_readquota(dir,  
+                format_maildirquota(user->pw_shell));  
+  
+            if (usage >= 90) {  
+                printf("%s %s %dn", user->pw_name, user->pw_shell, usage);  
+            }  
+        }  
+    }  
+  
+    return EXIT_SUCCESS;  
+}
+```
+
diff --git a/_posts/2008-12-05-peclhttp-and-sub-second-timeouts.md b/_posts/2008-12-05-peclhttp-and-sub-second-timeouts.md
new file mode 100644 (file)
index 0000000..641f70a
--- /dev/null
@@ -0,0 +1,22 @@
+---
+title: pecl_http and sub-second timeouts
+author: m6w6
+tags: 
+- PHP
+---
+
+Just a quick info, because I forget this again and again -- and it's not noted
+in the [documentation](http://php.net/manual/en/ref.http.php) yet either.
+
+Sub-second timeouts are supported by [libcurl](http://curl.haxx.se/libcurl/)
+and thus by [pecl_http](http://pecl.php.net/pecl_http) -- yes but only if
+libcurl is built with [(c-)ares](http://c-ares.haxx.se) support:
+
+&lt;quote url="[curl_easy_setopt.html](http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTTIMEOUTMS)">
+
+> If libcurl is built to use the standard system name resolver, that portion
+of the transfer will still use full-second resolution for timeouts with a
+minimum timeout allowed of one second.
+  
+&lt;/quote>
+
diff --git a/_posts/2009-04-10-php-commandline-highlighter.md b/_posts/2009-04-10-php-commandline-highlighter.md
new file mode 100644 (file)
index 0000000..701faac
--- /dev/null
@@ -0,0 +1,162 @@
+---
+title: PHP commandline highlighter
+author: m6w6
+tags: 
+- WTF 
+- PHP
+---
+
+Just chewed up a command line highlighter for php code.  
+It's hacky, but it fulfills my needs.
+
+```php
+class CHL {
+       protected $colors = array(
+               "start"         => "0:0",
+        "stop"         => "0:0",
+               "comment"       => "33",
+               "default"       => "30",
+               "html"          => "32",
+               "keyword"       => "34",
+               "string"        => "31",
+       );
+       protected $encoding = "UTF-8";
+    protected $tabstops;
+    protected $colwidth;
+       private $formats;
+       
+       public function __construct() {
+               if ($files = $this->setup()) {
+                       foreach ($files as $file) {
+                               $this->highlight(file_get_contents($file), $file);
+                       }
+               } elseif ($this->select()) {
+                       $this->highlight(file_get_contents("php://stdin"), "<STDIN>");
+               } else {
+                       $this->usage();
+               }
+       }
+       
+       public function __destruct() {
+               if ($this->tabstops) {
+                       echo "\033[3g";
+                       $this->tabstops = 8;
+                       $this->tabstops();
+               }
+       }
+       
+       protected function usage() {
+               printf("Usage:\n");
+               printf("\n");
+               printf(" %s [-e ENC] [-t TAB] [-f FILE, ...] [-c TOKEN=COLOR, ...]\n", basename($_SERVER["argv"][0]));
+               printf("\n");
+               printf(" -e ENC              specify the character set of the highlighted code\n");
+               printf(" -t TAB              specify the tab with\n");
+               printf(" -f FILE             specify one or more files to highlight, STDIN if omitted\n");
+               printf(" -c TOKEN=COLOR      specify the color code for the type of token\n");
+               printf("    possible tokens: %s\n", implode(", ",array_keys($this->colors)));
+               printf("\n");
+               exit;
+       }
+       
+       protected function setup() {
+               $files = array();
+               foreach (getopt("c:e:f:t:h") as $key => $val) {
+                       switch ($key) {
+                               case "h":
+                                       $this->usage();
+                                       break;
+                               case "c":
+                                       foreach ((array)$val as $col) {
+                                               list($type, $color) = explode("=", $col);
+                                               $this->colors[$type] = $color;
+                                       }
+                                       break;
+                               case "e":
+                                       $this->encoding = current(array_reverse((array)$val));
+                                       break;
+                               case "t":
+                                       if ($tabstops = (int) current(array_reverse((array)$val))) {
+                                               $this->tabstops = $tabstops;
+                                       }
+                                       break;
+                               case "f":
+                                       $files = (array) $val;
+                                       break;
+                       }
+        }
+
+               if (!$this->colwidth = getenv("COLUMNS")) {
+                       if (preg_match("/columns (\d+)/", shell_exec("stty -a"), $m)) {
+                               $this->colwidth = $m[1];
+                       } else {
+                               $this->colwidth = 80;
+                       }
+               }
+
+               $this->tabstops && $this->tabstops();
+               ini_set("highlight.comment", "comment");
+               ini_set("highlight.default", "default");
+               ini_set("highlight.html", "html");
+               ini_set("highlight.keyword", "keyword");
+               ini_set("highlight.string", "string");
+               $this->formats = array(
+                       // get rid of html
+                       "/\R/"                  => "",
+                       "/<br \/>/"             => "\n",
+                       "/<\/span>/"    => "",
+                       "/(&nbsp;){4}/" => "\t",
+                       "/&nbsp;/"              => " ",
+                       // convert colors
+                       "/<span style=\"color: comment\">/"     => $this->color("comment"),
+                       "/<span style=\"color: default\">/"     => $this->color("default"),
+                       "/<span style=\"color: html\">/"        => $this->color("html"),
+                       "/<span style=\"color: keyword\">/"     => $this->color("keyword"),
+            "/<span style=\"color: string\">/" => $this->color("string"),
+            // fix colors before newline
+            #"/((\033\[\d+m)+)([[:punct:][:space:]]*)(\r?\n)/s" => "\$1\$3\$4\$1",
+            // start/stop
+                       "/<code>/"              => $this->color("start"),
+                       "/<\/code>/"    => $this->color("stop", "", PHP_EOL),
+               );
+               return $files;
+       }
+       
+       protected function select() {
+               $r = $w = $e = array();
+               $r[] = STDIN;
+               if (stream_select($r, $w, $e, 0, 100) && $r[0]) {
+                       return true;
+               }
+               return false;
+    }
+
+    protected function tabstops() {
+        $colw = $this->colwidth;
+               $tabs = str_repeat(" ", $this->tabstops) . "\033H";
+               $tabs = str_repeat($tabs, $colw/$this->tabstops);
+               echo $tabs . "\r";
+       }
+       
+       protected function color($type, $prepend = "", $append = "") {
+               return $prepend . "\033[" . implode("m\033[", explode(":", $this->colors[$type])) . "m" . $append;
+       }
+       
+       protected function highlight($code, $name) {
+               echo "## Syntax highlighted code of $name:\n";
+               echo html_entity_decode(
+                       preg_replace(
+                               array_keys($this->formats),
+                               array_values($this->formats),
+                               highlight_string($code, true)
+                       ), 
+                       ENT_QUOTES, 
+                       $this->encoding
+        );
+        echo PHP_EOL;
+       }
+}
+```
+
+Cheers-
+
diff --git a/_posts/2009-04-20-looking-for-php-geeks-in-austria.md b/_posts/2009-04-20-looking-for-php-geeks-in-austria.md
new file mode 100644 (file)
index 0000000..478ec9c
--- /dev/null
@@ -0,0 +1,13 @@
+---
+title: Looking for PHP Geeks in Austria
+author: m6w6
+tags: 
+- PHP
+---
+
+You guessed. I'm desperately looking for decent PHP Coders in Vienna, Austria.
+
+The job posting (in german) can be found here:  
+<http://www.inqnet.at/job09.html>
+
+Just ping me if you're interested in an face-to-face interview.
diff --git a/_posts/2010-05-10-websockets-handshake-non-http-conforming.md b/_posts/2010-05-10-websockets-handshake-non-http-conforming.md
new file mode 100644 (file)
index 0000000..55ef8ff
--- /dev/null
@@ -0,0 +1,44 @@
+---
+title: WebSockets Handshake non HTTP conforming?
+author: m6w6
+tags: 
+- WTF 
+- PHP 
+- WEB
+---
+
+
+While skimming through the new [HTML5 WebSocket draft](http://dev.w3.org/html5/websockets/), 
+I noticed the following exemplar HTTP message demonstrating the client message of a WebSocket handshake:
+
+```http
+GET /demo HTTP/1.1
+Host: example.com
+Connection: Upgrade
+Sec-WebSocket-Key2: 12998 5 Y3 1  .P00
+Sec-WebSocket-Protocol: sample
+Upgrade: WebSocket
+Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5
+Origin: http://example.com
+
+^n:ds[4U
+```
+
+To me this looks non conforming to the [HTTP
+spec](http://www.w3.org/Protocols/rfc2616/rfc2616.html) due to the lack of an
+indicator that the request contains a message body.
+
+Quoting [the 4th paragraph of section 4.3 of
+RFC2616](http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3):
+
+> The **presence of a message-body** in a request **is signaled** by the
+inclusion of a **Content-Length or Transfer-Encoding header** field in the
+request's message-headers. A message-body MUST NOT be included in a request if
+the specification of the request method (section 5.1.1) does not allow sending
+an entity-body in requests. A server SHOULD read and forward a message-body on
+any request; if the request method does not include defined semantics for an
+entity-body, then the message-body SHOULD be ignored when handling the
+request.
+
+Huh?
+
diff --git a/_posts/2011-03-14-courier-imap-authdaemond-and-vpopmails-vchkpw.md b/_posts/2011-03-14-courier-imap-authdaemond-and-vpopmails-vchkpw.md
new file mode 100644 (file)
index 0000000..c5d2e76
--- /dev/null
@@ -0,0 +1,157 @@
+---
+title: courier imap, authdaemond and vpopmails vchkpw
+author: m6w6
+tags: 
+- WTF
+- SYS
+---
+
+A few years ago, it was possible to have courier-imap update the open-smtp
+relay file with it's authvchkpw module. This feature and thus imap-before-smtp
+disappeared with the introduction of courier-authdaemond because the vchkpw
+code of authdaemond does not have a chance to see the TCPREMOTEIP environment
+variable.
+
+I more or less lived with that, until a friend of mine got a new iphone...
+well yeah, one of those i-geeks, and that gadget apparently only supports
+imap, no pop.
+
+To re-enable imap-before-smtp I wrote a little setuid wrapper, calling
+vpopmails open_smtp_relay(). This wrapper has to replace the imapd command in
+your courier-imap startup script and will exec imapd, after opening the smtp
+relay, wile imap-login is still in place to authenticate via authdaemond's
+vchkpw module.
+
+```c
+#include <unistd.h>  
+#include <stdio.h>  
+#include <sys/types.h>  
+#include <vpopmail_config.h>  
+#include <vauth.h>  
+#include <vpopmail.h>  
+  
+#ifndef IMAPD  
+#   define IMAPD "/usr/bin/imapd"  
+#endif  
+  
+extern char **environ;  
+  
+int main(int argc, const char *argv[]) {  
+    if (argc != 2) {  
+        printf("1 NO argc != 2n");  
+        return -1;  
+    }  
+  
+    open_smtp_relay();  
+    /* no need to chown vpopmail.vchkpw the open-smtp file  
+     * because vchkpw used by qmail-pop3d is setuid root */  
+  
+    sleep(1);  
+  
+    if (setgid(VPOPMAILGID) || setuid(VPOPMAILUID)) {  
+        printf("1 NO setuid/gid, getuid=%dn", getuid());  
+        return -2;  
+    }  
+  
+    execl(IMAPD, IMAPD, argv[1], NULL);  
+  
+    printf("1 NO exec %s failedn", IMAPD);  
+    return -3;  
+}
+```
+
+So while this worked to my satisfaction, I noticed that the tcp.smtp.cdb not
+always contained the IPs of the open-smtp file:
+```sh
+$ for ip in $(sed -re 's/:.*//' < open-smtp); do   
+    cdbget $ip < tcp.smtp.cdb > /dev/null   
+        || echo "$ip is missing";   
+    done
+```
+
+I also found out that, while the [vpopmail FAQ](http://www.inter7.com/vpopmail/FAQ.txt) is claiming 
+that clearopensmtp is requesting locks on the open-smtp(.lock) file, the source does not read like
+it would.  
+
+I opened a [bug report](https://sourceforge.net/tracker/?func=detail&aid=3205655&group_id=85937&atid=577798)
+for that issue, but as you might have already guessed, I'm running all of this
+on an archaic debian box, where no upgrades are planned. So I came up with
+another home-brewed solution:
+
+```c
+#include <unistd.h>  
+#include <stdio.h>  
+#include <sys/types.h>  
+#include <vpopmail_config.h>  
+#include <vauth.h>  
+#include <vpopmail.h>  
+#include <fcntl.h>  
+  
+extern int get_write_lock(FILE*);  
+extern int lock_reg(int,int,int,off_t,int,off_t);  
+#define unlock(F) lock_reg(fileno(F), F_SETLK, F_UNLCK, 0, SEEK_SET, 0)  
+  
+int main(int argc, const char *argv[]) {  
+    FILE *fs_temp, *fs_smtp, *fs_lock = fopen(OPEN_SMTP_LOK_FILE, "w+");  
+    time_t clear = RELAY_CLEAR_MINUTES * 60, now = time(NULL);  
+    int cc = 0, rc = 0;  
+  
+    if (!fs_lock) {  
+        return -1;  
+    }  
+    if (get_write_lock(fs_lock)) {  
+        unlock(fs_lock);  
+        fclose(fs_lock);  
+        return -2;  
+    }     
+  
+    if (!(fs_temp = fopen(OPEN_SMTP_TMP_FILE ".clear", "w"))) {  
+        rc = -3;  
+    } else if (!(fs_smtp = fopen(OPEN_SMTP_CUR_FILE, "r+"))) {  
+        fclose(fs_temp);  
+        rc = -4;  
+    } else {  
+        while (!rc && !feof(fs_smtp)) {  
+            unsigned stime;  
+            char sdata[256];  
+  
+            switch (fscanf(fs_smtp, "%255st%un", sdata, &stime)) {  
+                case 2:  
+                    if ((clear + stime) >= now) {  
+                        fprintf(fs_temp, "%st%un", sdata, stime);  
+                    } else {  
+                        ++cc;  
+                    }  
+                    break;  
+  
+                default:  
+                    rc = -5;  
+                case EOF:  
+                    break;  
+            }  
+        }  
+        fclose(fs_smtp);  
+        fclose(fs_temp);  
+    }  
+  
+    if (!rc) {  
+        if (cc) {  
+            if (rename(OPEN_SMTP_TMP_FILE ".clear", OPEN_SMTP_CUR_FILE)) {  
+                rc = -6;  
+            } else if(update_rules()) {  
+                rc = -7;  
+            }  
+        } else {  
+            unlink(OPEN_SMTP_TMP_FILE ".clear");  
+        }  
+    }  
+  
+    unlock(fs_lock);  
+    fclose(fs_lock);  
+    return rc;
+}
+```
+
+It's not the prettiest piece of code, but it helps.  
+Well, maybe someone else running last-millenium software finds this useful
+
diff --git a/_posts/2011-03-18-javascript-delaying.md b/_posts/2011-03-18-javascript-delaying.md
new file mode 100644 (file)
index 0000000..efecf93
--- /dev/null
@@ -0,0 +1,44 @@
+---
+title: Javascript delaying
+author: m6w6
+tags: 
+- WEB
+---
+
+In need of executing Javascript after the page has loaded, or something else
+has been initialized I came up with a simple but useful tiny "Delayer":
+
+```js
+/**  
+ * @param handler a callback accepting Delayer.dispatch as argument  
+ */  
+function Delayer(handler) {  
+    var self = this;  
+  
+    this.dispatch = function() {  
+        for (var i = 0; i < self.length; ++i) {  
+            console.log("running delayed init "+i+": "+self[i]);  
+            self[i]();  
+        }  
+    };  
+  
+    if (typeof handler == "function" || handler instanceof Function) {  
+        handler(this.dispatch);  
+    }  
+}  
+  
+Delayer.prototype = Array.prototype;
+```
+
+It can be initialized the following way:
+```js
+/* e.g. with jQuery */  
+window.delayedInits = new Delayer($(document).ready);  
+/* e.g. with Facebook */  
+window.fbDelayedInits = new Delayer(function(dp){window.fbAsyncInit = dp;});
+```
+
+Then you push your work the usual way:
+```js
+delayedInits.push(function() {alert("Hello, delayed!");});
+```
diff --git a/_posts/2013-02-19-peclhttp-v2-http2-or-httpi-or-http.md b/_posts/2013-02-19-peclhttp-v2-http2-or-httpi-or-http.md
new file mode 100644 (file)
index 0000000..91defff
--- /dev/null
@@ -0,0 +1,29 @@
+---
+title: pecl_http-v2 - http2 or httpi or http-*
+author: m6w6
+tags: 
+- PHP
+---
+
+I'm pondering to release v2 of pecl_http with a different
+extension name than "http", but I cannot agree with myself what's worse:  
+
+### http2
+
+This might be confused with HTTP/2.0  
+
+### httpi
+
+There's mysqli following this approach, but I think this is pretty odd.  
+
+### Split it up
+
+Split the package up in several smaller sub-packages, like:
+
+  * http-common
+  * http-env
+  * http-client
+  * http-client-curl
+  * etc.
+
+If you have an opinion, or maybe even a better idea, please leave a comment.
diff --git a/_posts/2013-03-03-peclhttp-175.md b/_posts/2013-03-03-peclhttp-175.md
new file mode 100644 (file)
index 0000000..dc087e7
--- /dev/null
@@ -0,0 +1,30 @@
+---
+title: pecl_http-1.7.5
+author: m6w6
+tags: 
+- PHP
+---
+
+[pecl_http-1.7.5](http://pecl.php.net/package/pecl_http/1.7.5) has been
+released today.
+
+Nearly a year and 170k downloads after the last release (1.7.4 was released
+April 2nd 2012).  
+  
+It fixes a single bug:  
+
+  * [Bug #64310](http://bugs.php.net/64310) (weak etags W/"abc" are quoted as "W/"abc"")
+
+
+The same user (thanks Niko), discovered a peculiarity of libcurl:
+
+  * If you utilize libcurl's _TIMECOND_ feature through pecl_http's _lastmodified_ request option, 
+    libcurl ignores response bodies from servers that do not closely follow the RFC and send a _200 OK_  
+    response instead of a _304 Not Modified_  when the condition is unmet.
+
+Slightly more background information is available at the relevant [bug
+report](http://bugs.php.net/64298).
+
+
+Please leave a comment, if you have an opinion about which component's
+behavior is arguable here.
diff --git a/_posts/2013-06-18-hear-hear.md b/_posts/2013-06-18-hear-hear.md
new file mode 100644 (file)
index 0000000..c566e59
--- /dev/null
@@ -0,0 +1,28 @@
+---
+title: Hear, hear
+author: m6w6
+tags: 
+- PHP
+scripts:
+- https://platform.twitter.com/widgets.js
+---
+
+I was about to write "in early February" but actually it already was in late January
+that I stumbled over this tweet:
+
+<blockquote class="twitter-tweet" markdown="1">
+I'm still ready & willing to hire a
+[#PHP](https://twitter.com/search?q=%23PHP&src=hash) internals coder to work
+on PHP fulltime. Amazing place to work: <http://t.co/GX4wtPSc>
+
+— Don MacAskill (@DonMacAskill) [January 18, 2013](https://twitter.com/DonMacAskill/statuses/292117608076021760)
+</blockquote>
+
+Fast-forward five months – now I am very excited to be able to announce that
+the Awesomes over at [SmugMug, Inc](http://www.smugmug.com/). have hired me to
+work full-time on the core of PHP.  
+  
+Hide [bugs.php.net](http://bugs.php.net/), expect massive amounts of commits,
+sleep well. Thank you for reading the simple words of the proudest man alive.
+Thank you SmugMug!  
+
diff --git a/_posts/2013-12-09-evolution-of.md b/_posts/2013-12-09-evolution-of.md
new file mode 100644 (file)
index 0000000..e7eeaab
--- /dev/null
@@ -0,0 +1,41 @@
+---
+title: Evolution of $
+author: m6w6
+tags: 
+- PHP
+---
+
+Today I realized an important and probably very obvious fact: we all change. Of
+course, you will say. Surely most of us will agree to that, but the important
+thing about that is also realizing that we drift away from things we loved.
+Okay, so what am I actually talking about? :)  
+  
+I talk about software development, specifically development of and with PHP.
+We've seen some radical proposals in the nearer past and in deed are still
+seeing those for PHP, the language. Often, I was inclined to think "cool,
+that's a great idea, let's improve in that direction."  
+  
+PHP was and is a huge success, it attracts a lot of awesome people, sometimes
+becoming unhappy with the language's principles and resulting limitiations,
+like its simplicity, its forgiving nature and the enigne's effort to come to
+an end for this request, i.e. to die. Looking at the larger frameworks which
+have evolved the last few years, they head into a clear direction: strictly
+object oriented programming with
+RidiculouslyLongClassNamesLikeFoundInOtherStrictlyObjectOrientedLanguages.
+Anything non object oriented seems to be verboten. But this is not of what PHP
+was meant to be and it is very hard to change something that late in the game
+in such drastical ways. I don't think PHP can change as fast as we do, it's
+actually much longer around than most of us call ourself programmers.  
+  
+What I mean to say is, don't be angry with PHP the language, don't force it to
+change in a way it's not supposed to survive, stop proposing language level
+changes in a weekly manner, don't be afraid to change yourself. Don't be
+afraid to advance yourself. Don't be afraid to change the language you program
+in. BOOM, I said it. Yes, don't be afraid to explore other possibilities that
+better support your principles instead of fighting them.  
+  
+I'm not saying go away, I'm saying go ahead, or at least I mean to.  
+  
+Sorry for the fast write-up, all the typos and errors. Have a nice start into
+your week!
+
diff --git a/_posts/2015-08-11-testing-php-extensions-on-travis-ci.md b/_posts/2015-08-11-testing-php-extensions-on-travis-ci.md
new file mode 100644 (file)
index 0000000..d2c99a2
--- /dev/null
@@ -0,0 +1,54 @@
+---
+title: Testing PHP extensions on Travis-CI
+author: m6w6
+tags: 
+- PHP
+---
+
+Testing PECL extensions on Travis-CI has always been
+cumbersome for me; build PHP in different versions and debug/threadsafe
+flavors, install PECL dependencies and so on, which usually results in a mess
+of command line scripts, repeated for every extension.  
+  
+Enter [travis-pecl](https://github.com/m6w6/travis-pecl).  
+  
+This tiny support bin comes with a Makefile and small PHP scripts to generate
+the build matrix and check your package.xml file. It supports building PHP in
+a wide variety of flavors, installing PECL dependencies from the PECL website
+or from bundled [pharext](https://github.com/m6w6/pharext) packages and
+running the testsuite with a comprehensive set of commands.  
+  
+Let's look at a few commands with a properly set up environment from the test
+matrix:  
+
+```yaml
+env:  
+ - PHP=5.6 enable_debug=yes with_iconv=yes enable_json=yes  
+```
+### Build PHP:  
+```sh
+make -f travis/pecl/Makefile php  
+```
+### Install a PECL dependency:  
+```sh
+make -f travis/pecl/Makefile pecl PECL=propro  
+```
+### Install a PECL dependency from a [pharext](https://github.com/m6w6/pharext) package, located in travis/:  
+```sh
+make -f travis/pecl/Makefile pharext/raphf-phpng  
+```
+### Build the currently checked out extension:  
+```sh
+make -f travis/pecl/Makefile ext PECL=http  
+```
+### Run the testsuite:  
+```sh
+make -f travis/pecl/Makefile test  
+```
+
+Finally, check out the [README](https://github.com/m6w6/travis-pecl/blob/master/README.md) 
+and have a look at a couple of complete examples here:  
+
+  * [ext-apfd/gen_travis_yml.php](https://github.com/m6w6/ext-apfd/blob/master/gen_travis_yml.php)
+  * [ext-http/scripts/gen_travis_yml.php](https://github.com/m6w6/ext-http/blob/master/scripts/gen_travis_yml.php)
diff --git a/_posts/2015-08-19-blank-dell-on-displayport.md b/_posts/2015-08-19-blank-dell-on-displayport.md
new file mode 100644 (file)
index 0000000..0f3dd24
--- /dev/null
@@ -0,0 +1,20 @@
+---
+title: Blank DELL on DisplayPort
+author: m6w6
+tags: 
+- WTF 
+- SYS
+--- 
+
+I've been struggling since ever with my DELL U3014 on the DisplayPort
+saying there's no signal after a power cycle of the monitor.  
+  
+I just found a solution to bring the monitor back to life without rebooting
+the box; just ssh into and issue:  
+
+```shell  
+$ DISPLAY=:0 xset dpms force off  
+$ DISPLAY=:0 xset dpms force on  
+```
+
+I'm running Gnome3 on Arch Linux, so YMMV.  
diff --git a/_posts/2016-04-16-debian-disabling-sslv3-in-courier-server.md b/_posts/2016-04-16-debian-disabling-sslv3-in-courier-server.md
new file mode 100644 (file)
index 0000000..92f6e3c
--- /dev/null
@@ -0,0 +1,265 @@
+--- 
+title: 'Debian: disabling SSLv3 in courier server' 
+author: m6w6 
+tags: 
+- WTF 
+- SYS
+--- 
+
+Debian wheezy (currently oldstable) ships courier-0.68 which was probably released on 2012. 
+"Probably", because, head over to the [Courier website](http://www.courier-mta.org/) and 
+try to find the NEWS/ChangeLog.
+
+## The Problem
+
+Anyway. Courier-0.68 has built-in openssl support on Debian and it initializes a SSL 
+context the following way:
+
+```c
+ctx=SSL_CTX_new(protocol && strcmp(protocol, "SSL3") == 0
+                ? SSLv3_method():
+                protocol && strcmp(protocol, "SSL23") == 0
+                ? SSLv23_method():
+                TLSv1_method());
+
+// ...
+SSL_CTX_set_options(ctx, SSL_OP_ALL);
+
+if (!ssl_cipher_list)
+        ssl_cipher_list="SSLv3:TLSv1:HIGH:!LOW:!MEDIUM:!EXP:!NULL:!aNULL@STRENGTH";
+
+SSL_CTX_set_cipher_list(ctx, ssl_cipher_list);
+```
+
+#### Some clarifications:
+
+* `SSLv3_method` would **only** allow SSLv3
+* `TLSv1_method` would **only** allow TLSv1.0
+* `SSLv23_method` is "the general-purpose version-flexible SSL/TLS method"
+
+So, if we do not want to limit ourselves to TLSv1.0, i.e. allow TLSv1.0, TLSv1.1 and TLSv1.2, 
+we have to limit our protocol version support through other means.
+
+Openssl-1.0.1 (remember, we're on Debian wheezy) does neither come with `TLS_method()` the 
+generic TLS-only method, nor does it come with `SSL_CTX_set_min_proto_version` and we cannot 
+disable SSLv3 with the cipher list if we also want to allow TLSv1.0.
+
+## Solution 1: Upgrading to Jessie
+
+What if we upgrade to Debian jessie (current stable)? Jessie ships courier-0.73, so let's see 
+how SSL context intitialization looks there:
+
+```c
+options=SSL_OP_ALL;
+
+method=((!protocol || !*protocol)
+        ? NULL:
+        strcmp(protocol, "SSL3") == 0
+                ? SSLv3_method():
+        strcmp(protocol, "SSL23") == 0
+                ? SSLv23_method():
+        strcmp(protocol, "TLSv1") == 0
+        ? TLSv1_method():
+#ifdef HAVE_TLSV1_1_METHOD
+        strcmp(protocol, "TLSv1.1") == 0
+        ? TLSv1_1_method():
+#endif
+#ifdef HAVE_TLSV1_2_METHOD
+        strcmp(protocol, "TLSv1.2") == 0
+        ? TLSv1_2_method():
+#endif
+        NULL);
+
+if (!method)
+{
+        method=SSLv23_method();
+        options|=SSL_OP_NO_SSLv2;
+}
+
+ctx=SSL_CTX_new(method);
+
+// ...
+SSL_CTX_set_options(ctx, options);
+
+if (!ssl_cipher_list)
+        ssl_cipher_list="SSLv3:TLSv1:HIGH:!LOW:!MEDIUM:!EXP:!NULL:!aNULL@STRENGTH";
+
+SSL_CTX_set_cipher_list(ctx, ssl_cipher_list);
+```
+
+Jessie also comes with openssl-1.0.1, so the situation would not improve for our undertaking 
+by upgrading to jessie.
+
+## Solution 2: Augmenting SSL_CTX_new
+
+What I came up with, is augmenting `SSL_CTX_new` and setting the desired `SSL_OP_NO_SSLv3` on 
+each newly created SSL context.
+
+```c
+#include <stdio.h>
+#include <dlfcn.h>
+#include <openssl/ssl.h>
+
+static void *lib;
+static void *new_sym;
+static void *opt_sym;
+
+static void dl() {
+        char *error;
+
+        if (!lib) {
+                lib = dlopen("libssl.so", RTLD_LAZY|RTLD_LOCAL);
+                if (!lib) {
+                        fprintf(stderr, "dlopen: %s\n", dlerror());
+                        exit(1);
+                }   
+                dlerror();
+        }   
+    
+        if (!new_sym) {
+                *(void **) &new_sym = dlsym(lib, "SSL_CTX_new");
+                if ((error = dlerror())) {
+                        fprintf(stderr, "dlsym: %s\n", error);
+                        dlclose(lib);
+                        exit(1);
+                }   
+        }   
+
+        if (!opt_sym) {
+                *(void **) &opt_sym = dlsym(lib, "SSL_CTX_ctrl");
+                if ((error = dlerror())) {
+                        fprintf(stderr, "dlsym: %s\n", error);
+                        dlclose(lib);
+                        exit(1);
+                }   
+        }   
+}
+
+SSL_CTX *SSL_CTX_new(const SSL_METHOD *m) 
+{
+        SSL_CTX *ctx;
+
+        dl();
+
+        ctx = ((SSL_CTX *(*)(const SSL_METHOD*))new_sym)(m);
+
+        if (ctx) {
+                ((long (*)(SSL_CTX *, int, long, void*))opt_sym)(ctx, SSL_CTRL_OPTIONS, SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3, NULL);
+        }   
+        return ctx;
+}
+```
+
+This is the source of a tiny shared library pre-defining our `SSL_CTX_new`; to build like e.g.
+
+`gcc -ldl -fPIC -shared -o preload.so preload.c`
+
+It does the following:
+
+* augments `SSL_CTX_new` with our own version, 
+  i.e. whenever courier calls `SSL_CTX_new` our own version gets called
+* when it's called the first time, it
+ * `dlopen`'s libssl
+ * fetches the addresses of the original `SSL_CTX_new` and `SSL_CTX_ctrl` 
+   (which is the actual function `SSL_CTX_set_options` calls)
+* calls the original `SSL_CTX_new` to actually create the SSL context
+* calls `SSL_CTX_ctrl` on the new context with the options we want to set (`SSL_OP_NO_SSLv3`)
+* returns the context to the caller
+
+### Usage
+
+Courier config files are basically shell scripts which set a environment variables, so we'll 
+enable it as follows:
+
+```sh
+cd /etc/courier
+cat >>esmtpd >>esmtpd-msa >>esmtpd-ssl \
+    >>pop3d >>pop3d-ssl \
+    >>imapd >>imapd-ssl \
+    >>courierd <<EOF
+LD_PRELOAD=/path/to/preload.so
+EOF
+```
+
+Then restart each courier service.
+
+### Verifying
+
+Last, we have to verify that our solution actually works:
+
+```sh
+openssl s_client \
+       -CApath /etc/ssl/certs/ \
+       -starttls imap \
+       -connect localhost:143 \
+       -crlf -quiet -ssl3 \
+       <<<LOGOUT
+139690858608296:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1261:SSL alert number 40
+139690858608296:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:599:
+```
+
+A bunch of errors. "Good"! :)
+
+Let's see if we can still connect with TLSv1+:
+
+```sh
+openssl s_client \
+       -CApath /etc/ssl/certs/ \
+       -starttls imap \
+       -connect localhost:143 \
+       -crlf -quiet -tls1 \
+       <<<LOGOUT
+depth=2 ...
+verify return:1
+depth=1 ...
+verify return:1
+depth=0 ...
+verify return:1
+. OK CAPABILITY completed
+* BYE Courier-IMAP server shutting down
+LOGOUT OK LOGOUT completed
+```
+
+Awesome. Mission accomplished.
+
+## Addendum
+
+Here's my cipher list for the interested:
+
+```sh
+openssl ciphers -v 'HIGH+aRSA:+kEDH:+kRSA:+SHA:+3DES:!kSRP' \
+  | awk '{ printf "%-28s %-8s %-8s %-18s %-16s\n",$1,$2,$3,$5,$6 }'
+```
+
+Which results in the following ciphers:
+
+```
+ECDHE-RSA-AES256-GCM-SHA384  TLSv1.2  Kx=ECDH  Enc=AESGCM(256)    Mac=AEAD
+ECDHE-RSA-AES256-SHA384      TLSv1.2  Kx=ECDH  Enc=AES(256)       Mac=SHA384
+ECDHE-RSA-AES128-GCM-SHA256  TLSv1.2  Kx=ECDH  Enc=AESGCM(128)    Mac=AEAD
+ECDHE-RSA-AES128-SHA256      TLSv1.2  Kx=ECDH  Enc=AES(128)       Mac=SHA256
+DHE-RSA-AES256-GCM-SHA384    TLSv1.2  Kx=DH    Enc=AESGCM(256)    Mac=AEAD
+DHE-RSA-AES256-SHA256        TLSv1.2  Kx=DH    Enc=AES(256)       Mac=SHA256
+DHE-RSA-AES128-GCM-SHA256    TLSv1.2  Kx=DH    Enc=AESGCM(128)    Mac=AEAD
+DHE-RSA-AES128-SHA256        TLSv1.2  Kx=DH    Enc=AES(128)       Mac=SHA256
+AES256-GCM-SHA384            TLSv1.2  Kx=RSA   Enc=AESGCM(256)    Mac=AEAD
+AES256-SHA256                TLSv1.2  Kx=RSA   Enc=AES(256)       Mac=SHA256
+AES128-GCM-SHA256            TLSv1.2  Kx=RSA   Enc=AESGCM(128)    Mac=AEAD
+AES128-SHA256                TLSv1.2  Kx=RSA   Enc=AES(128)       Mac=SHA256
+ECDHE-RSA-AES256-SHA         SSLv3    Kx=ECDH  Enc=AES(256)       Mac=SHA1
+ECDHE-RSA-AES128-SHA         SSLv3    Kx=ECDH  Enc=AES(128)       Mac=SHA1
+DHE-RSA-AES256-SHA           SSLv3    Kx=DH    Enc=AES(256)       Mac=SHA1
+DHE-RSA-CAMELLIA256-SHA      SSLv3    Kx=DH    Enc=Camellia(256)  Mac=SHA1
+DHE-RSA-AES128-SHA           SSLv3    Kx=DH    Enc=AES(128)       Mac=SHA1
+DHE-RSA-CAMELLIA128-SHA      SSLv3    Kx=DH    Enc=Camellia(128)  Mac=SHA1
+AES256-SHA                   SSLv3    Kx=RSA   Enc=AES(256)       Mac=SHA1
+CAMELLIA256-SHA              SSLv3    Kx=RSA   Enc=Camellia(256)  Mac=SHA1
+AES128-SHA                   SSLv3    Kx=RSA   Enc=AES(128)       Mac=SHA1
+CAMELLIA128-SHA              SSLv3    Kx=RSA   Enc=Camellia(128)  Mac=SHA1
+ECDHE-RSA-DES-CBC3-SHA       SSLv3    Kx=ECDH  Enc=3DES(168)      Mac=SHA1
+EDH-RSA-DES-CBC3-SHA         SSLv3    Kx=DH    Enc=3DES(168)      Mac=SHA1
+DES-CBC3-SHA                 SSLv3    Kx=RSA   Enc=3DES(168)      Mac=SHA1
+```
+
+Note, that courier actually does **not** support `ECDH` key exchange, but I didn't exclude it for 
+the sake of simplicity for using the same cipher list for every server (e.g. web etc.)
diff --git a/_sass/_colors.scss b/_sass/_colors.scss
new file mode 100644 (file)
index 0000000..38f2e67
--- /dev/null
@@ -0,0 +1,55 @@
+$view-backgroud-color: #000;
+$page-background-color: rgba(255, 255, 255, 0.90);
+$code-background-color: rgba(255, 255, 255, 0.50);
+
+$shadow-color: #666;
+$border-color: #ccc;
+
+$header-color: #000;
+$body-color: #000;
+$code-color: #821;
+
+$a-link-color: #178;
+$a-active-color: #182;
+$a-visited-color: #218;
+$a-hover-color: #182;
+
+@media (prefers-color-scheme: light) {
+       :root {
+               --view-backgroud-color: #000;
+               --page-background-color: rgba(255, 255, 255, 0.90);
+               --code-background-color: rgba(255, 255, 255, 0.50);
+
+               --shadow-color: #666;
+               --border-color: #ccc;
+
+               --header-color: #000;
+               --body-color: #000;
+               --code-color: #821;
+
+               --a-link-color: #178;
+               --a-active-color: #182;
+               --a-visited-color: #218;
+               --a-hover-color: #182;
+       }
+}
+
+@media (prefers-color-scheme: dark) {
+       :root {
+               --view-backgroud-color: #000;
+               --page-background-color: rgba(17, 17, 17, 0.90);
+               --code-background-color: rgba(102, 102, 102, 0.50);
+
+               --shadow-color: #666;
+               --border-color: #999;
+
+               --header-color: #f0f0f0;
+               --body-color: #ddd;
+               --code-color: #c43;
+
+               --a-link-color: #8df;
+               --a-active-color: #8f9;
+               --a-visited-color: #98f;
+               --a-hover-color: #8f9;
+       }
+}
diff --git a/_sass/_common.scss b/_sass/_common.scss
new file mode 100644 (file)
index 0000000..37c1e3b
--- /dev/null
@@ -0,0 +1,22 @@
+@import "_colors";
+
+.email:after {
+       content: "\6d\69\6b\65\40\70\68\70\2e\6e\65\74";
+}
+.jabber:after {
+       content: "\6d\36\77\36\40\6a\61\62\62\65\72\2e\63\63\63\2e\64\65";
+}
+.twitter-tweet-rendered {
+       margin-left: auto;
+       margin-right: auto;
+}
+
+.pubinfo, .breadcrumbs {
+       font-style: italic;
+       opacity: .7;
+}
+
+.cc-sa img {
+       border: none;
+       vertical-align: middle;
+}
diff --git a/_sass/_fonts.scss b/_sass/_fonts.scss
new file mode 100644 (file)
index 0000000..f25bdf4
--- /dev/null
@@ -0,0 +1,42 @@
+$body-font: 'Linux Biolinum';
+$header-font: 'Linux Libertine Display', Georgia, 'Times New Roman', Times, serif;
+$code-font: 'DejaVu Sans Mono', 'Bitstream Vera Mono', 'Menlo', 'Consolas', 'Andale Mono', 'Lucida Console', 'Monospace', monospace;
+
+//$font-size: 14px;
+//$line-height: 130%;
+$font-size: 12px;
+$line-height: 180%;
+
+@font-face {
+       font-family: 'Linux Libertine Display';
+       src: url('subset-LinLibertineDisplay.woff2') format('woff2'), url('subset-LinLibertineDisplay.woff') format('woff');
+       font-weight: normal;
+       font-style: normal;
+}
+
+@font-face {
+       font-family: 'Linux Biolinum';
+       src: local('Linux Biolinum Italic'), local('LinBiolinumI'),
+       url('subset-LinBiolinumI.woff2') format('woff2'),
+       url('subset-LinBiolinumI.woff') format('woff');
+       font-weight: normal;
+       font-style: italic;
+}
+
+@font-face {
+       font-family: 'Linux Biolinum';
+       src: local('Linux Biolinum'), local('LinBiolinum'),
+       url('subset-LinBiolinum.woff2') format('woff2'),
+       url('subset-LinBiolinum.woff') format('woff');
+       font-weight: normal;
+       font-style: normal;
+}
+
+@font-face {
+       font-family: 'Linux Biolinum';
+       src: local('Linux Biolinum Bold'), local('LinBiolinumB'),
+       url('subset-LinBiolinumB.woff2') format('woff2'),
+       url('subset-LinBiolinumB.woff') format('woff');
+       font-weight: bold;
+       font-style: normal;
+}
diff --git a/_sass/index.scss b/_sass/index.scss
new file mode 100644 (file)
index 0000000..b8bb06b
--- /dev/null
@@ -0,0 +1,311 @@
+@import '_colors';
+@import '_fonts';
+@import '_common';
+
+html {
+       background: $view-backgroud-color url("lapalma-c.jpg") fixed no-repeat;
+       background: var(--view-backgroud-color) url("lapalma-c.jpg") fixed no-repeat;
+       background-size: cover;
+       height: 100%;
+       font-size: $font-size;
+}
+
+body {
+       font-family: $body-font;
+       line-height: $line-height;
+       margin: 0;
+       color: $body-color;
+       color: var(--body-color);
+
+       &.default {
+               display: block;
+       }
+       >div {
+               background: $page-background-color;
+               background: var(--page-background-color);
+               max-width: 1000px;
+               margin: 0 auto;
+               header>h1 {
+                       margin-top: 0;
+               }
+       }
+}
+
+@mixin responsive($rel-size) {
+       body {
+               font-size: $rel-size;
+               >div {
+                       padding: $rel-size;
+               }
+       }
+       section {
+               margin-top: $rel-size;
+       }
+       p {
+               margin: $rel-size;
+       }
+       ul li {
+               margin-left: $rel-size;
+       }
+       dd+dt {
+               margin-top: $rel-size/4;
+       }
+       th, td {
+               padding: $rel-size;
+               .career-table & {
+                       padding: $rel-size/10 $rel-size/2;
+               }
+       }
+       h1, h2, h3, h4, h5, h6, th {
+               text-shadow: 0 0 $rel-size/3 $shadow-color;
+       }
+       h2+h3, h3+h4, h4+h5, h5+h6 {
+               margin-top: -$rel-size/2;
+       }
+       h2~h3 {
+               margin-left: $rel-size/4;
+       }
+       h3~h4 {
+               margin-left: $rel-size/2;
+       }
+       h4~h5 {
+               margin-left: $rel-size;
+       }
+       h5~h6 {
+               margin-left: $rel-size;
+       }
+       h2 {
+               padding-top: $rel-size;
+       }
+       pre {
+               padding: 0 $rel-size;
+               code {
+                       padding: $rel-size !important;
+                       font-size: $rel-size/1.66;
+                       border-radius: $rel-size/2;
+                       box-shadow: 0 0 $rel-size/4 $shadow-color;
+                       box-shadow: 0 0 $rel-size/4 var(--shadow-color);
+               }
+       }
+       code {
+               padding: $rel-size/20 $rel-size/10;
+               font-size: $rel-size/1.5;
+               border-radius: $rel-size/5;
+       }
+       .cc-sa {
+               font-size: $rel-size/2;
+               margin-top: $rel-size*2;
+       }
+       .pubinfo, .breadcrumbs {
+               font-size: $rel-size/1.5;
+               margin: -$rel-size 0 $rel-size $rel-size*2;
+       }
+       .box-of-links a {
+               line-height: 2*$rel-size;
+               min-width: 8*$rel-size;
+               svg {
+                       width: $rel-size*1.5;
+                       height: $rel-size*1.5;
+               }
+               &.gnupg svg {
+                       width: $rel-size*1.8;
+                       height: $rel-size*1.8;
+               }
+               &.jabber svg {
+                       width: $rel-size*1.8;
+                       height: $rel-size*1.8;
+               }
+               &.flattr-com svg {
+                       height: $rel-size*1.2;
+               }
+               &.openhub-net svg {
+                       height: $rel-size*1.3;
+               }
+               &.smugmug-com svg {
+                       height: $rel-size*1.2;
+               }
+       }
+}
+
+@media (min-width: 1440px) {
+       @include responsive(1.8rem);
+}
+@media (max-width: 1440px) {
+       @include responsive(1.7rem);
+}
+@media (max-width: 1280px) {
+       @include responsive(1.6rem);
+}
+@media (max-width: 1080px) { /* includes 1024, 900 */
+       @include responsive(1.5rem);
+}
+@media (max-width: 800px) { /* includes 768 */
+       @include responsive(1.4rem);
+}
+@media (max-width: 720px) {
+       @include responsive(1.3rem);
+}
+
+h1, h2, h3, h4, h5, h6, th {
+       font-family: $header-font;
+       color: $header-color;
+       color: var(--header-color);
+       font-weight: normal;
+       line-height: 110%;
+}
+
+h2 {
+       border-top: 1px solid $border-color;
+       border-top: 1px solid var(--border-color);
+}
+
+ul {
+       li {
+               list-style-type: circle;
+               li {
+                       margin-left: auto;
+               }
+       }
+}
+
+header, main, section, footer {
+       clear: both;
+}
+
+footer {
+       text-align: center;
+       opacity: .5;
+}
+
+
+code {
+       font-family: $code-font;
+       color: $code-color;
+       color: var(--code-color);
+       background: $code-background-color;
+       background: var(--code-background-color);
+}
+pre {
+       code {
+               background: black;
+               color: lime;
+               display: inline-block !important;
+               box-sizing: border-box;
+               max-width: 100%;
+               line-height: 133%;
+       }
+}
+
+dt {
+       font-weight: bold;
+}
+
+.presence-table svg {
+       vertical-align: middle;
+}
+
+.career-table {
+
+       min-width: 80%;
+       border-spacing: 0;
+       th {
+               border-left: 1rem solid $border-color;
+               border-left: 1rem solid var(--border-color);
+               font-size: x-small;
+       }
+       tr:first-child th {
+               border-top-left-radius: 2rem;
+       }
+       tr:last-child th {
+               border-bottom-left-radius: 2rem;
+       }
+       tr:nth-child(2) th { opacity: .95; }
+       tr:nth-child(3) th { opacity: .90; }
+       tr:nth-child(4) th { opacity: .85; }
+       tr:nth-child(5) th { opacity: .80; }
+       tr:nth-child(6) th { opacity: .75; }
+       tr:nth-child(7) th { opacity: .70; }
+       tr:nth-child(8) th { opacity: .65; }
+       tr:nth-child(9) th { opacity: .60; }
+       tr:nth-child(10) th { opacity: .55; }
+       tr:nth-child(11) th { opacity: .50; }
+       tr:nth-child(12) th { opacity: .45; }
+       tr:nth-child(13) th { opacity: .40; }
+       tr:nth-child(14) th { opacity: .35; }
+       tr:nth-child(15) th { opacity: .30; }
+       tr:nth-child(16) th { opacity: .25; }
+       tr:nth-child(17) th { opacity: .20; }
+       tr:nth-child(18) th { opacity: .15; }
+       tr:nth-child(n+19):nth-child(-n+99) th { opacity: .1; }
+       tr.career-change {
+               +tr {
+                       td {
+                               border-top: 1px solid $border-color;
+                               border-top: 1px solid var(--border-color);
+                       }
+               }
+       }
+}
+table {
+       border: none;
+}
+th, td {
+       text-align: left;
+       vertical-align: middle;
+}
+a {
+       text-decoration: none;
+       &:link {
+               color: $a-link-color;
+               color: var(--a-link-color);
+       }
+       &:visited {
+               color: $a-visited-color;
+               color: var(--a-visited-color);
+       }
+       &:hover {
+               color: $a-hover-color;
+               color: var(--a-hover-color);
+               text-decoration: underline;
+       }
+       &:active {
+               color: $a-active-color;
+               color: var(--a-active-color);
+       }
+       &[rel="external"]:after {
+               content: " ↗";
+               font-size: 1rem;
+               font-weight: bold;
+       }
+       &[download]:after {
+               content: " ↓";
+               font-size: 1rem;
+               font-weight: bold;
+       }
+}
+img#portrait {
+       border: 1px solid #999;
+       box-shadow: 0 0 1em $shadow-color;
+       box-shadow: 0 0 1em var(--shadow-color);
+       margin-right: 1em;
+       margin-bottom: 1em;
+       float: left;
+}
+
+.cc-sa {
+       border-top: 1px solid $border-color;
+       border-top: 1px solid var(--border-color);
+}
+
+a svg {
+       vertical-align: middle;
+}
+.box-of-links {
+       display: flex;
+       flex-wrap: wrap;
+       a {
+               display: block;
+               padding: 1rem;
+               white-space: nowrap;
+       }
+}
diff --git a/_sass/post.scss b/_sass/post.scss
new file mode 100644 (file)
index 0000000..08ee66c
--- /dev/null
@@ -0,0 +1,197 @@
+@import '_fonts';
+@import '_common';
+
+html {
+       font-size: $font-size;
+       font-family: $code-font;
+       background: #111  url("lapalma-o-10.jpg") fixed no-repeat;
+       background-size: cover;
+       height: 100%;
+       box-sizing: border-box;
+}
+
+body {
+       line-height: $line-height*1.33;
+       background: transparent url("lapalma-o-100.jpg") fixed no-repeat;
+       background-size: cover;
+       min-height: 100%;
+       box-sizing: border-box;
+       margin: 0;
+       padding: 1rem;
+
+       &.post {
+               display: block;
+       }
+
+       >div {
+               max-width: 120ch;
+               border: 1px outset black;
+               border-top-left-radius: 1.33rem;
+               border-top-right-radius: 1.33rem;
+               margin: auto;
+               >header {
+                       background: linear-gradient(180deg, rgba(175,175,175,.8), rgba(240,240,240,.8));
+                       padding: .33rem;
+                       border-top-left-radius: 1rem;
+                       border-top-right-radius: 1rem;
+
+                       font-family: sans-serif;
+                       text-align: center;
+                       font-weight: bold;
+
+                       display: grid;
+
+                       >h1 {
+                               grid-column: 1 / 8;
+                               margin: 0;
+                               font-size: 1.6rem;
+                       }
+                       >div {
+                               grid-column: 9 / 10;
+                               text-align: right;
+                               margin-right: .5rem;
+                               span {
+                                       display: inline-block;
+                                       border: 1px solid #000;
+                                       border-radius: .2rem;
+                                       background: linear-gradient(0deg, #afafaf, #f0f0f0);
+                                       width: 1.2rem;
+                                       line-height: 120%;
+                                       text-align: center;
+                                       padding: .1rem;
+                                       margin: .2rem;
+                                       animation: 1s linear 0s background;
+                                       &:hover {
+                                               background: linear-gradient(180deg, #afafaf, #f0f0f0);
+                                       }
+                               }
+                       }
+               }
+               >main {
+                       >div {
+                               background: #333;
+                               color: #eee;
+                               font-size: 1.5em;
+                               padding: 1rem;
+                               p {
+                                       &::before {
+                                               content: "~$ \A";
+                                               color: lime;
+                                               font-weight: 100;
+                                       }
+                               }
+                               blockquote p::before, .pubinfo p::before {
+                                       content: none;
+                                       color: white;
+                               }
+                               blockquote p:first-child::before {
+                                       content: "» ";
+                                       vertical-align: baseline;
+                                       font-size: 4rem;
+                                       opacity: .33;
+                               }
+                               blockquote p:last-child::after {
+                                       content: " «";
+                                       vertical-align: bottom;
+                                       font-size: 4rem;
+                                       opacity: .33;
+
+                               }
+                               &:last-child::after {
+                                       content: "_";
+                                       animation: 1s steps(2,end) 0s infinite blink;
+                               }
+
+                               h1,h2,h3,h4,h5,h6 {
+                                       font-weight: normal;
+                                       font-size: 1em;
+                                       color: lime;
+                                       margin-top:2em;
+                                       &::before {
+                                               content: "# ";
+                                       }
+                                       &::after {
+                                               content: " ⏎";
+                                       }
+                               }
+                       }
+               }
+       }
+
+       >footer {
+               line-height: 150%;
+               text-align: center;
+               max-width: 120ch;
+               margin: auto;
+               border-bottom-left-radius: 1.33rem;
+               border-bottom-right-radius: 1.33rem;
+//             background: rgba(255,255,255, .80);
+               background: linear-gradient(0deg, rgba(175,175,175,.8), rgba(240,240,240,.8));
+               border: 1px outset black;
+       }
+}
+
+.pubinfo {
+       text-align: right;
+       font-size: 1rem;
+}
+
+.cc-sa {
+       width: 50%;
+       padding: 1rem;
+       margin: auto;
+}
+
+@keyframes blink {
+       from {background: transparent;}
+       to {background: white;}
+}
+
+a {
+       &:link {
+               color: #00afff;
+       }
+       &:visited {
+               color: #cf00af;
+               opacity: .8;
+       }
+       &:hover {
+               color: #30ff00;
+       }
+}
+
+pre {
+       line-height: 150%;
+       font-size: 1.2rem;
+
+       background: black;
+       color: white;
+
+       border: 1px solid #1c1;
+
+       counter-increment: examples;
+       counter-reset: lines;
+       &::after {
+               background: #1c1;
+               color: black;
+               display: block;
+               content: " example" counter(examples) ".txt  " counter(lines) "L                                                                1,1     Top";
+       }
+
+       code {
+               opacity: .8;
+               span.newline {
+                       counter-increment: lines;
+                       &::before {
+                               content: counter(lines) " ";
+                               width: 2rem;
+                               display: inline-block;
+                               text-align: right;
+                               opacity: .5;
+                       }
+               }
+               padding: 1em 1em 1em 1em;
+               display: block;
+               overflow-x: auto;
+       }
+}
diff --git a/assets/cc-sa.png b/assets/cc-sa.png
new file mode 100644 (file)
index 0000000..e76aeff
Binary files /dev/null and b/assets/cc-sa.png differ
diff --git a/assets/index.scss b/assets/index.scss
new file mode 100644 (file)
index 0000000..7fe96e5
--- /dev/null
@@ -0,0 +1,4 @@
+---
+---
+
+@import "index";
diff --git a/assets/lapalma-c.jpg b/assets/lapalma-c.jpg
new file mode 100644 (file)
index 0000000..fe1e83b
Binary files /dev/null and b/assets/lapalma-c.jpg differ
diff --git a/assets/lapalma-o-10.jpg b/assets/lapalma-o-10.jpg
new file mode 100644 (file)
index 0000000..e63f466
Binary files /dev/null and b/assets/lapalma-o-10.jpg differ
diff --git a/assets/lapalma-o-100.jpg b/assets/lapalma-o-100.jpg
new file mode 100644 (file)
index 0000000..0ed19aa
Binary files /dev/null and b/assets/lapalma-o-100.jpg differ
diff --git a/assets/lapalma-o-progressive.jpg b/assets/lapalma-o-progressive.jpg
new file mode 100644 (file)
index 0000000..9e00145
Binary files /dev/null and b/assets/lapalma-o-progressive.jpg differ
diff --git a/assets/lapalma-o.jpg b/assets/lapalma-o.jpg
new file mode 100644 (file)
index 0000000..1df4a75
Binary files /dev/null and b/assets/lapalma-o.jpg differ
diff --git a/assets/post.scss b/assets/post.scss
new file mode 100644 (file)
index 0000000..fb042b4
--- /dev/null
@@ -0,0 +1,4 @@
+---
+---
+
+@import "post";
diff --git a/assets/rouge.css b/assets/rouge.css
new file mode 100644 (file)
index 0000000..52970bf
--- /dev/null
@@ -0,0 +1,78 @@
+.highlight table td { padding: 5px; }
+.highlight table pre { margin: 0; }
+.highlight, .highlight .w {
+  color: #f8f8f2;
+  background-color: #272822;
+}
+.highlight .err {
+  color: #272822;
+  background-color: #f92672;
+}
+.highlight .c, .highlight .ch, .highlight .cd, .highlight .cm, .highlight .cpf, .highlight .c1, .highlight .cs {
+  color: #75715e;
+}
+.highlight .cp {
+  color: #f4bf75;
+}
+.highlight .nt {
+  color: #f4bf75;
+}
+.highlight .o, .highlight .ow {
+  color: #f8f8f2;
+}
+.highlight .p, .highlight .pi {
+  color: #f8f8f2;
+}
+.highlight .gi {
+  color: #a6e22e;
+}
+.highlight .gd {
+  color: #f92672;
+}
+.highlight .gh {
+  color: #66d9ef;
+  background-color: #272822;
+  font-weight: bold;
+}
+.highlight .k, .highlight .kn, .highlight .kp, .highlight .kr, .highlight .kv {
+  color: #ae81ff;
+}
+.highlight .kc {
+  color: #fd971f;
+}
+.highlight .kt {
+  color: #fd971f;
+}
+.highlight .kd {
+  color: #fd971f;
+}
+.highlight .s, .highlight .sa, .highlight .sb, .highlight .sc, .highlight .dl, .highlight .sd, .highlight .s2, .highlight .sh, .highlight .sx, .highlight .s1 {
+  color: #a6e22e;
+}
+.highlight .sr {
+  color: #a1efe4;
+}
+.highlight .si {
+  color: #cc6633;
+}
+.highlight .se {
+  color: #cc6633;
+}
+.highlight .nn {
+  color: #f4bf75;
+}
+.highlight .nc {
+  color: #f4bf75;
+}
+.highlight .no {
+  color: #f4bf75;
+}
+.highlight .na {
+  color: #66d9ef;
+}
+.highlight .m, .highlight .mb, .highlight .mf, .highlight .mh, .highlight .mi, .highlight .il, .highlight .mo, .highlight .mx {
+  color: #a6e22e;
+}
+.highlight .ss {
+  color: #a6e22e;
+}
diff --git a/assets/subset-LinBiolinum.woff b/assets/subset-LinBiolinum.woff
new file mode 100644 (file)
index 0000000..c4b1c7f
Binary files /dev/null and b/assets/subset-LinBiolinum.woff differ
diff --git a/assets/subset-LinBiolinum.woff2 b/assets/subset-LinBiolinum.woff2
new file mode 100644 (file)
index 0000000..e3f5696
Binary files /dev/null and b/assets/subset-LinBiolinum.woff2 differ
diff --git a/assets/subset-LinBiolinumB.woff b/assets/subset-LinBiolinumB.woff
new file mode 100644 (file)
index 0000000..d241f0f
Binary files /dev/null and b/assets/subset-LinBiolinumB.woff differ
diff --git a/assets/subset-LinBiolinumB.woff2 b/assets/subset-LinBiolinumB.woff2
new file mode 100644 (file)
index 0000000..fe9095e
Binary files /dev/null and b/assets/subset-LinBiolinumB.woff2 differ
diff --git a/assets/subset-LinBiolinumI.woff b/assets/subset-LinBiolinumI.woff
new file mode 100644 (file)
index 0000000..b4351c2
Binary files /dev/null and b/assets/subset-LinBiolinumI.woff differ
diff --git a/assets/subset-LinBiolinumI.woff2 b/assets/subset-LinBiolinumI.woff2
new file mode 100644 (file)
index 0000000..bb005fe
Binary files /dev/null and b/assets/subset-LinBiolinumI.woff2 differ
diff --git a/assets/subset-LinLibertineDisplay.woff b/assets/subset-LinLibertineDisplay.woff
new file mode 100644 (file)
index 0000000..a0d7b02
Binary files /dev/null and b/assets/subset-LinLibertineDisplay.woff differ
diff --git a/assets/subset-LinLibertineDisplay.woff2 b/assets/subset-LinLibertineDisplay.woff2
new file mode 100644 (file)
index 0000000..ebc0a6b
Binary files /dev/null and b/assets/subset-LinLibertineDisplay.woff2 differ
diff --git a/blog.html b/blog.html
new file mode 100644 (file)
index 0000000..16b5375
--- /dev/null
+++ b/blog.html
@@ -0,0 +1,49 @@
+---
+layout: default
+title: "Mike's sudden inspirations"
+permalink: blog.html
+styles: assets/index.css
+---
+{% include head.html %}
+<body class="blog">
+<div>
+       <header>
+               <h1>{{ page.title }}</h1>
+               <p class="breadcrumbs">
+                       » <a href="{{ site.url }}">{{ site.title }}</a>
+               </p>
+       </header>
+       <main>
+               {% assign y_posts = site.posts | group_by_exp: "post", "post.date | slice: 0, 4" %}
+               {% for y in y_posts %}
+                       <h2 id="{{ y.name }}">{{ y.name }}</h2>
+                       {% assign m_posts = y.items | group_by_exp: "item", "item.date | slice: 5, 2" %}
+                       {% for m in m_posts %}
+                               {% assign month = m.items | map: "date" | first | date: "%B" %}
+                               <h3 id="{{ y.name }}{{ m.name }}">{{ month }}</h3>
+                               {% assign d_posts = m.items | group_by_exp: "item", "item.date | slice: 8, 2" %}
+                               {% for d in d_posts %}
+                                       {% assign day = d.items | map: "date" | first | date: "%A, %e" %}
+                                       <h4 id="{{ y.name }}{{ m.name }}{{ d.name }}">{{ day }}</h4>
+                                       <ul>
+                                               {% for post in d.items %}
+                                               <li>
+                                                       <a href=".{{ post.url }}">{{ post.title }}</a> in
+                                                       {% assign last_tag = post.tags | last %}
+                                                       {% for tag in post.tags %}
+                                                       <a class="tag" href="blog/tags/{{ tag }}/"
+                                                       >{{ tag }}</a>{% if tag != last_tag %}, {% endif %}
+                                                       {% endfor %}
+                                               </li>
+                                               {% endfor %}
+                                       </ul>
+                               {% endfor %}
+                       {% endfor %}
+               {% endfor %}
+       </main>
+       <footer>
+               {% include ccsa.html %}
+       </footer>
+</div>
+</body>
+{% include foot.html %}
diff --git a/favicon.ico b/favicon.ico
new file mode 100644 (file)
index 0000000..1b55a1a
Binary files /dev/null and b/favicon.ico differ
diff --git a/index.html b/index.html
new file mode 100644 (file)
index 0000000..3d74384
--- /dev/null
@@ -0,0 +1,200 @@
+---
+title: Michael Wallner (m6w6)
+layout: default
+styles: assets/index.css
+---
+               <header>
+                       <div>
+                               <img id="portrait" src="m6w6.jpg" height="185" width="140" alt="">
+                       </div>
+                       <h1>
+                               {{ site.title }} <small>&lt;<span class="email"></span>&gt;</small>
+                       </h1>
+                       <p>
+                               {{ site.description }}
+                       </p>
+               </header>
+               <section>
+                       <h2 id="identity">Identity</h2>
+                       <h3>PGP, GPG</h3>
+                       <p><code>1EC3 C71D DD63 5831 A337 D684 480E 3E14 B0A4 C7C7</code></p>
+                       <div class="box-of-links">
+                               <a href="./openpgp.key" type="text/plain" download="mike@php.net.key"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="4rem" height="4rem" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path d="M5.83 10A2.99 2.99 0 0 0 3 8a3 3 0 0 0-3 3a3 3 0 0 0 3 3c1.31 0 2.42-.83 2.83-2H8v2h2v-2h1v-2H5.83M3 12a1 1 0 0 1-1-1a1 1 0 0 1 1-1a1 1 0 0 1 1 1a1 1 0 0 1-1 1m13-8a4 4 0 0 0-4 4a4 4 0 0 0 4 4a4 4 0 0 0 4-4a4 4 0 0 0-4-4m0 6.1A2.1 2.1 0 0 1 13.9 8A2.1 2.1 0 0 1 16 5.9a2.1 2.1 0 1 1 0 4.2m0 2.9c-2.67 0-8 1.33-8 4v3h16v-3c0-2.67-5.33-4-8-4m6.1 5.1H9.9V17c0-.64 3.1-2.1 6.1-2.1c2.97 0 6.1 1.46 6.1 2.1v1.1z" fill="#626262"/></svg>
+                                       pubkey</a>
+                               <a href="https://keybase.io/m6w6"
+                                        rel="external" class="keybase-io"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="4rem" height="4rem" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path d="M10.446 21.371a.953.953 0 1 1-.955-.954c.524 0 .951.431.951.955m5.922-.001a.953.953 0 1 1-.958-.954c.526 0 .954.431.954.955m4.544-9.159l-.156-.204c-.046-.06-.096-.116-.143-.175c-.045-.061-.094-.113-.141-.169c-.104-.12-.209-.239-.319-.359l-.076-.08l-.091-.099l-.135-.131c-.015-.018-.032-.034-.05-.053a10.87 10.87 0 0 0-3.955-2.504l-.23-.078l.035-.083a4.108 4.108 0 0 0-.12-3.255a4.11 4.11 0 0 0-2.438-2.16c-.656-.216-1.23-.319-1.711-.305c-.033-.105-.1-.577.496-1.848L10.663 0l-.287.399c-.33.455-.648.895-.945 1.328a1.857 1.857 0 0 0-1.245-.58L6.79 1.061h-.012c-.033-.003-.07-.003-.104-.003c-.99 0-1.81.771-1.87 1.755l-.088 1.402v.003a1.876 1.876 0 0 0 1.755 1.979l1.002.061c-.065.84.073 1.62.405 2.306a11.279 11.279 0 0 0-3.66 2.484C.913 14.391.913 18.051.913 20.994v1.775l1.305-1.387c.266.93.652 1.807 1.145 2.615H5.06a9.197 9.197 0 0 1-1.68-3.848l1.913-2.03l-.985 3.091l1.74-1.268c3.075-2.234 6.744-2.75 10.91-1.529c1.805.532 3.56.039 4.473-1.257l.104-.165c.091.498.141.998.141 1.496c0 1.563-.255 3.687-1.38 5.512h1.611c.776-1.563 1.181-3.432 1.181-5.512c-.001-2.199-.786-4.421-2.184-6.274zM8.894 6.191c.123-1.002.578-1.949 1.23-2.97a1.36 1.36 0 0 0 1.283.749c.217-.008.605.025 1.233.232c.714.236 1.286.744 1.608 1.425s.349 1.442.079 2.149c-.173.445-.454.82-.806 1.109l-.408-.502l-.002-.003a1.468 1.468 0 0 0-2.059-.205c-.334.27-.514.66-.534 1.058c-1.2-.541-1.8-1.643-1.628-3.041l.004-.001zm4.304 5.11l-.519.425a.228.228 0 0 1-.323-.032l-.111-.135a.238.238 0 0 1 .034-.334l.51-.42l-1.055-1.299a.307.307 0 0 1 .044-.436a.303.303 0 0 1 .434.041l2.963 3.645a.309.309 0 0 1-.168.499a.315.315 0 0 1-.31-.104l-.295-.365l-1.045.854a.244.244 0 0 1-.154.055a.237.237 0 0 1-.186-.09l-.477-.579a.24.24 0 0 1 .035-.336l1.051-.857l-.426-.533l-.002.001zM7.753 4.866l-1.196-.075a.463.463 0 0 1-.435-.488l.09-1.401a.462.462 0 0 1 .461-.436h.024l1.401.091a.459.459 0 0 1 .433.488l-.007.101a9.269 9.269 0 0 0-.773 1.72h.002zm12.524 11.481c-.565.805-1.687 1.081-2.924.718c-3.886-1.141-7.396-.903-10.468.701l1.636-5.123l-5.291 5.609c.099-3.762 2.453-6.966 5.758-8.311c.471.373 1.034.66 1.673.841c.16.044.322.074.48.102a1.41 1.41 0 0 0 .21 1.407l.075.09c-.172.45-.105.975.221 1.374l.475.582a1.39 1.39 0 0 0 1.079.513c.321 0 .635-.111.886-.314l.285-.232c.174.074.367.113.566.113a1.45 1.45 0 0 0 .928-.326c.623-.51.72-1.435.209-2.06l-1.67-2.056c.145-.117.281-.244.408-.381c.135.037.271.078.4.12c.266.097.533.198.795.315a9.55 9.55 0 0 1 2.771 1.897c.029.03.059.055.085.083l.17.175a9.168 9.168 0 0 1 .35.387l.126.15c.045.053.086.104.13.16l.114.15c.04.051.079.102.117.154c.838 1.149.987 2.329.404 3.157v.005zM7.719 4.115l-.835-.051l.053-.835l.834.051l-.052.835z" fill="#626262"/></svg>
+                                       keybase.io</a>
+                               <!-- a href="https://sks-keyservers.net/pks/lookup?op=vindex&search=0xB0A4C7C7&fingerprint=on"
+                                        rel="external" class="gnupg"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="4rem" height="4rem" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 70 70"><path d="m173.45252,38.04702zm-158.54822,-4.85442l2.8387,0l0,-8.5449c0,-9.5791 7.7686,-17.3477 17.3476,-17.3477c9.5793,0 17.3474,7.7686 17.3474,17.3477l0,8.4605c-0.041,0.0287 -0.0818,0.0568 -0.122,0.0844l0.0003,0l-0.0264,0.0178l-0.003,0.002l-0.003,0.0017l-0.003,0.0019l-0.0131,0.009l-0.0155,0.0105l-0.003,0.0021l-0.017,0.0115l-0.0008,0.0006l-0.007,0.0045l-0.004,0.0025l-0.008,0.0057l-0.002,0.0013l-0.0103,0.0069l-0.0001,0l-0.0103,0.007l-0.0139,0.0093l-0.007,0.0045l-0.006,0.0037l-0.005,0.0031l-0.0156,0.0106l-0.0151,0.0099l-0.0007,0.0005l-0.0196,0.013l-0.004,0.0028l-0.0239,0.0157l-0.002,0.0014l-0.01,0.0065l-0.0003,0.0002l-0.004,0.0024l-0.0313,0.0205l-0.005,0.0032l-0.007,0.0045l-0.003,0.0019l-0.002,0.0015l-0.0161,0.0105l-0.002,0.0009l-0.0004,0.0003l-0.001,0.0006l-0.0184,0.0119l-0.004,0.0025l-0.006,0.0038l-0.006,0.0035l-0.004,0.0027l-0.01,0.0063l-0.009,0.0058l-0.0007,0.0003l-0.01,0.0063l-0.001,0.0007l-0.009,0.0054l-0.003,0.0018l-0.007,0.0045l-0.005,0.0028l-0.005,0.0032l-0.006,0.0039l-0.004,0.0022l-0.0527,0.0331l-0.0112,0.0068l-0.003,0.0017l-0.0282,0.0175l-0.002,0.0014l-0.0321,0.0195l-0.0008,0.0005l-0.002,0.0014l-0.009,0.0052l-0.0005,0.0003l-0.009,0.0056l-0.001,0.0006l-0.008,0.0049l-0.008,0.0048l-0.001,0.0007l-0.004,0.0026l-0.0139,0.0083l-0.007,0.0045l-0.0106,0.0064l-0.031,0.0182l-0.031,0.0182l-0.0312,0.0183l-0.0312,0.0184l-0.063,0.0368l-0.0317,0.0184l-0.0318,0.0186l-0.0132,0.0076l-0.0831,0.048l-0.0323,0.0186l-0.0326,0.0186l-0.0326,0.0188l-0.0429,0.0245l-0.056,0.0317l-0.0332,0.0188l-0.129,0.0725l-0.006,0.003l-0.034,0.0189l-0.034,0.0191l-0.008,0.0042l-0.0453,0.025l-0.1017,0.0559l-0.0478,0.0262c-0.0488,0.0265 -0.0981,0.0532 -0.1479,0.0799l-0.0127,0.0069l-0.0232,0.0124l-0.0724,0.0385l-0.0364,0.0194l-0.006,0.0032l-0.0669,0.0353l-0.0003,0.0002l-0.037,0.0193l-0.0106,0.0055l-0.0638,0.0334l-0.0374,0.0194l-0.0343,0.0177c-0.0467,0.0242 -0.0939,0.0484 -0.1415,0.0726l-0.0389,0.0198c-0.0559,0.0283 -0.1124,0.0568 -0.1695,0.0852l-0.0005,0.0002c-0.0545,0.0271 -0.1095,0.0543 -0.1651,0.0815l-0.0552,0.027c-0.0604,0.0293 -0.1213,0.0589 -0.183,0.0884l-0.0003,0c-3.445,1.6457 -8.9698,3.3967 -19.458,4.1496c-7.5135,0.5398 -12.0684,3.8468 -15.0393,7.8378l0,-13.6174l0.0043,0zm10.8293,0l18.7139,0l0,-8.5449c0,-5.1671 -4.19,-9.3571 -9.3569,-9.3571c-5.1668,0 -9.357,4.19 -9.357,9.3571l0,8.5449zm24.2416,1.3477c-0.056,0.0283 -0.1123,0.0567 -0.1695,0.0852m-6.8566,-23.1288c-2.2246,-1.3293 -4.8253,-2.0941 -7.6044,-2.0941c-7.6178,0 -13.897,5.7395 -14.7512,13.1284c2.2332,-6.9868 8.7795,-12.0479 16.5063,-12.0479c2.0525,0 4.0218,0.358 5.8493,1.0136zm12.3278,24.9666l0,24.4853l-34.5405,0c3.8076,-2.117 6.6453,-1.9014 11.3452,-1.7528c6.4003,0.2024 13.4724,-2.4788 16.9505,-6.029c3.4785,-3.5506 -0.3148,-0.8401 -4.2524,0.1588c-3.9382,0.9983 -11.5585,1.1046 -16.6522,-0.2343c16.043,0.2187 22.2867,-4.9709 25.8324,-9.6186c3.5455,-4.6476 -1.5335,-0.8069 -4.8238,0.7953c-3.2901,1.6037 -9.0284,2.7494 -15.3383,1.9139c9.5512,-0.0198 16.8185,-4.7928 21.4791,-9.7186z" fill="#626262"/></svg>
+                                       sks-keyservers.net</a -->
+                       </div>
+               </section>
+               <section>
+                       <h2 id="contact">Contact</h2>
+                       <div class="box-of-links">
+                               <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#109;&#105;&#107;&#101;&#64;&#112;&#104;&#112;&#46;&#110;&#101;&#116;"
+                                        class="email"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="4.60rem" height="4rem" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 512 448"><path d="M469 21H43q-18 0-30.5 13T0 64v256q0 17 12.5 30T43 363h426q18 0 30.5-13t12.5-30V64q0-17-12.5-30T469 21zm-40 43L256 166L83 64h346zM43 320V90l202 121q2 2 11 2t11-2L469 90v230H43z" fill="#626262"/></svg></a>
+                               <a href="irc://chat.freenode.net/m6w6,isnick" class="irc"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="4rem" height="4rem" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path opacity=".3" d="M20 4H4v13.17L5.17 16H20V4zm-6 10H6v-2h8v2zm4-3H6V9h12v2zm0-3H6V6h12v2z" fill="#626262"/><path d="M20 18c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14zm-16-.83V4h16v12H5.17L4 17.17zM6 12h8v2H6zm0-3h12v2H6zm0-3h12v2H6z" fill="#626262"/></svg>
+                                       m6w6@freenode</a>
+                               <a href="irc://irc.efnet.info/m6w6,isnick" class="irc"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="4rem" height="4rem" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path d="M4 4h16v12H5.17L4 17.17V4m0-2c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2H4zm2 10h8v2H6v-2zm0-3h12v2H6V9zm0-3h12v2H6V6z" fill="#626262"/></svg>
+                                       m6w6@efnet</a>
+                               <!-- a href="&#115;&#107;&#121;&#112;&#101;&#58;&#108;&#105;&#118;&#101;&#58;&#109;&#54;&#119;&#54;&#95;&#49;" class="skype"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="3.84rem" height="4rem" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 464 488"><path d="M441 267q3-15 3-33q0-88-63-151T230 20q-16 0-33 3q-32-19-68-19q-53 0-91 37.5T0 133q0 36 19 68q-2 11-2 33q0 89 62.5 151.5T230 448q18 0 34-3q30 19 68 19q53 0 91-37.5t38-91.5q0-37-20-68zm-109 64q-13 18-40 31q-27 11-62 11q-43 0-70-15q-20-11-32-29q-13-17-13-36q0-9 8-17q7-7 19-7q9 0 16 5q7 6 12 17q4 10 11 21q7 8 18 14q12 5 30 5q25 0 41-11q16-10 16-27q0-11-8-21q-10-8-23-12t-36-9q-33-8-52-16q-21-9-34-25q-12-16-12-39t13-40q14-18 38-26q23-10 58-10q26 0 46 6q20 8 32 17q13 10 19 21q6 12 6 22t-8 18q-7 8-19 8q-11 0-16-5q-6-6-11-15q-8-16-19-23q-9-8-34-8q-22 0-36 9q-13 9-13 21q0 8 4 13q4 6 13 10q7 4 16 6q5 2 28 7q27 7 44 12q18 6 34 15q14 11 22 24q7 13 7 34q0 25-13 44z" fill="#626262"/></svg>
+                                       m6w6@skype</a -->
+                               <a href="&#120;&#109;&#112;&#112;&#58;&#109;&#54;&#119;&#54;&#64;&#106;&#97;&#98;&#98;&#101;&#114;&#46;&#99;&#99;&#99;&#46;&#100;&#101;"
+                                        class="jabber"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="4rem" height="4rem" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path d="M12 15.4C9.75 13.09 8 9.54 8 6L2 4c0 5.65 4.33 10.11 8.55 12.66C9.38 17.5 8.15 18 7 18v1c1.2 0 3.03-.54 5-1.54c1.97 1 3.8 1.54 5 1.54v-1c-1.15 0-2.38-.5-3.55-1.34C17.66 14.11 22 9.65 22 4l-6 2c0 3.54-1.75 7.09-4 9.4z" fill="#626262"/></svg></a>
+                       </div>
+               </section>
+               <section>
+                       <h2>Social</h2>
+                       <div class="box-of-links">
+                               <!-- a href="https://about.me/m6w6" rel="external" class="about-me"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="2em" height="2em" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path d="M19.536 9.15c-1.373 0-2.133 1.014-2.294 2.116h4.608c-.125-1.05-.867-2.115-2.314-2.115m-2.26 3.617c.235 1.156 1.193 1.97 2.532 1.97c.725 0 1.77-.27 2.384-.914l1.175 1.35c-1.064 1.11-2.653 1.426-3.74 1.426c-2.64 0-4.697-1.906-4.697-4.606c0-2.535 1.894-4.62 4.57-4.62c2.585 0 4.5 1.98 4.5 4.604v.766h-6.723v.023zm-6.487 3.83v-5.69c0-.976-.435-1.536-1.338-1.536c-.814 0-1.355.585-1.717 1.007v6.24h-2.35v-5.7c0-.976-.415-1.532-1.318-1.532c-.813 0-1.375.586-1.717 1.006v6.24H0V7.508h2.35v1.15c.4-.464 1.302-1.26 2.71-1.26c1.247 0 2.096.525 2.477 1.59c.524-.762 1.5-1.59 2.91-1.59c1.7 0 2.69 1.01 2.69 2.962v6.24h-2.353l.005-.006z" fill="#626262"/></svg>
+                                       About</a -->
+                               <a href="https://twitter.com/_m6w6" rel="external" class="twitter-com"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="2.08em" height="2em" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 464 448"><path d="M410 174q40-3 50-29q-8 5-24 7.5t-30-1.5q-2-8-2-11q-10-35-38-57.5T306 64q3-2 11-4l9-2q10-3 15.5-7t3.5-8q-1-2-5.5-2T329 42.5T317.5 46l-11 4l-6.5 2q23-8 25-19q-21 3-36 17q6-8 7-13q-40 25-73 111q-22-22-34-28q-46-26-119-52q-2 36 40 58q-8-1-29 3q7 36 52 46q-20 1-32 13q18 32 57 27q-25 12-16.5 27.5T173 255q-37 37-88 37T2 259q42 57 107 78.5t125.5 9.5T344 295.5t63-95.5q36 1 55-20q-31 4-52-6z" fill="#626262"/></svg>
+                                       Twitter</a>
+                               <!-- a href="https://flattr.com/profile/m6w6" rel="external" class="flattr-com"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="2em" height="2em" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path d="M1.906 12C1.906 6.432 6.432 1.906 12 1.906c.048 0 4.003 0 5.455.002L14.53 4.834l1.344 1.344L21.903 0H12C5.373 0 0 5.373 0 12v9.331l1.91-1.759v-.096c-.002-.244-.004-7.404-.004-7.476zM24 2.668l-1.91 1.76v.096L22.093 12c0 5.568-4.528 10.094-10.093 10.094c-.048 0-4.003 0-5.455-.002l2.925-2.926l-1.344-1.344L2.097 24H12c6.627 0 12-5.373 12-12V2.668z" fill="#626262"/></svg>
+                                       Flattr</a -->
+                               <!-- a href="https://www.openhub.net/accounts/mike" rel="external" class="openhub-net"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="2em" height="2em" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 96 96"><g transform="translate(0.000000,96.000000) scale(0.100000,-0.100000)" fill="none"><path d="M0 480 l0 -480 480 0 480 0 0 480 0 480 -480 0 -480 0 0 -480z m368 169 c152 -74 126 -315 -39 -359 -142 -38 -277 97 -239 239 13 49 62 109 105 127 46 20 122 17 173 -7z m216 5 c12 -11 16 -35 16 -85 l0 -69 90 0 90 0 0 69 c0 88 22 115 74 95 20 -8 21 -43 1 -50 -12 -5 -15 -31 -15 -144 0 -151 -3 -170 -30 -170 -24 0 -30 19 -30 91 l0 59 -90 0 -90 0 0 -62 c0 -71 -9 -92 -36 -86 -17 3 -19 16 -22 153 -2 119 -6 151 -17 158 -18 10 -20 43 -2 50 24 10 46 7 61 -9z" fill="#626262"/><path d="M245 613 c-110 -29 -131 -193 -32 -253 117 -72 249 79 172 196 -28 43 -92 69 -140 57z" fill="#626262"/></g></svg>
+                                       Openhub</a -->
+                               <a href="https://github.com/m6w6" rel="external" class="github-com"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="2.08em" height="2em" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 464 448"><path d="M338 13q12 29 4 53q18 15 24 47t-3 62q11 1 32.5 1.5t38 2T462 184q-67-8-88-7q-14 5-15 8q73 6 102 16q-77-13-102-14q-22 43-87 48q1 3 7.5 11.5T287 264t-.5 40.5T290 338q2 4 7 8t7 7q-8 8-22 1.5T266 338q-2-8 0-38t-6-32q0 4-2 40t3 39q1 3 5 8.5t3 10.5q-22 2-28.5-13t-6-46.5T233 264q-4 1-4 16q0 5 .5 16.5t.5 18t-1 16.5t-3 15.5t-6 11t-10 7.5t-15 1q-1-5 3-10.5t5-7.5q5-8 3-38.5t0-41.5q-9 6-7 33.5t-2 41.5q-4 9-15.5 12.5T160 355q1-5 7-9t8-8q4-1 2.5-20.5T177 292q-46 9-63-19q-1-3-5-12t-8-14q-2-2-9-7t-9-11q19-5 37.5 16.5T154 268q6 0 24-6q5-18 16-26q-70-11-89-49q-55 3-102 15q31-12 101-16q-1-4-3.5-6t-6.5-2.5t-7.5-1t-9 0t-7.5.5q-38 2-68 7q22-8 96-8q-9-24-4.5-58T115 70q-5-13-4-30t8-27q26 1 58 23q33-8 69-7q5 0 16.5 3t16.5 2t15-7t11-7q15-7 33-7z" fill="#626262"/></svg>
+                                       Github</a>
+                               <a href="https://m6w6.smugmug.com" rel="external" class="smugmug-com"
+                               ><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="1.92em" height="2em" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 464 488"><path d="M188 36q0 14-13 24.5T143 71q-18 0-31-10.5T99 36t13-24t31-10q19 0 32 10t13 24zM344 2q-19 0-32 10t-13 24t13 24.5T344 71q18 0 31-10.5T388 36t-13-24t-31-10zm118 175q0 13-9 43t-30.5 72t-51.5 79.5t-78 64T190 462q-69 0-114.5-30.5t-60.5-76t-12-96T27 165q5-10 10.5-16.5T46 141l3-1h381q4 0 9 1.5t14 11t9 24.5zm-46 9H67q-19 38-21 84t20 88q34 58 124 58q42 0 79.5-20t61.5-47.5t43.5-62T403 228t13-42z" fill="#626262"/></svg>
+                                       SmugMug</a>
+                       </div>
+                       <h2 id="blog">Blog &mdash; <a href="blog/">Mike's sudden Inspirations</a></h2>
+                       <ul>
+                               {% assign m6w6_posts = site.posts | where: "author", "m6w6" | slice: 0, 3 %}
+                               {% for post in m6w6_posts  %}
+                                       <li><small><a href=".{{ post.url }}">{{ post.title }}</a>
+                                               &mdash; posted {{ post.date | date_to_long_string: "ordinal" }}</small></li>
+                               {%  endfor %}
+                       </ul>
+               </section>
+               <section>
+                       <h2 id="career">Career</h2>
+                       <table class="career-table">
+                               <tr class="career-current">
+                                       {% assign Y = "now" | date: "%Y" %}
+                                       {% assign rowspan = Y | minus: 2013 | plus: 1 %}
+                                       <th>{{ Y }}</th>
+                                       <td rowspan="{{ rowspan }}"><a href="https://www.smugmug.com" rel="external">SmugMug Inc.</a></td>
+                                       <td rowspan="{{ rowspan }}">Sorcerer</td>
+                                       <td rowspan="{{ rowspan }}">Remote</td>
+                                       <td></td>
+                               </tr>
+                               {% assign last_Y = Y | minus: 1 %}
+                               {% for y in (2014..last_Y) reversed %}
+                               <tr><th>{{ y }}</th></tr>
+                               {% endfor %}
+                               <tr class="career-change"><th rowspan="2">2013</th></tr>
+                               <tr>
+                                       <td rowspan="7">INQNET</td>
+                                       <td rowspan="7">Software Developer</td>
+                                       <td rowspan="7">Vienna</td>
+                                       <td></td>
+                               </tr>
+                               <tr><th>2012</th></tr>
+                               <tr><th>2011</th></tr>
+                               <tr><th>2010</th></tr>
+                               <tr><th>2009</th></tr>
+                               <tr><th>2008</th></tr>
+                               <tr class="career-change"><th rowspan="2">2007</th></tr>
+                               <tr>
+                                       <td rowspan="6">IWORKS</td>
+                                       <td rowspan="6">Freelancer</td>
+                                       <td rowspan="6">Remote</td>
+                                       <td></td>
+                               </tr>
+                               <tr><th>2006</th></tr>
+                               <tr><th>2005</th></tr>
+                               <tr><th>2004</th></tr>
+                               <tr><th>2003</th></tr>
+                               <tr class="career-start"><th>2002</th></tr>
+                       </table>
+               </section>
+               <section>
+                       <h2 id="opensource">Open source</h2>
+                       <table class="opensource-table">
+                               <tr>
+                                       <th>libmemcached</th>
+                                       <td>C/C++ library for <code>memcached(1)</code> (resurrected)</td>
+                                       <td>
+                                               <a href="https://github.com/m6w6/libmemcached" rel="external"
+                                               >Github</a>,
+                                               <a href="https://git.m6w6.name/?p=m6w6/libmemcached" rel="external"
+                                               >Mirror</a>,
+                                               <a href="https://m6w6.github.io/libmemcached" rel="external"
+                                               >Docs</a>,
+                                               <a href="https://artifacts.m6w6.name/libmemcached/" rel="external"
+                                               >Artifacts</a>
+                                       </td>
+                               </tr>
+                               <!-- tr>
+                                       <th>pecl/psi</th>
+                                       <td>PHP System Interface</td>
+                                       <td>
+                                               <a href="https://github.com/m6w6/ext-psi" rel="external"
+                                                       >Github</a>,
+                                               <a href="https://git.m6w6.name/?p=m6w6/ext-psi" rel="external"
+                                                       >Mirror</a>,
+                                               <a href="http://pecl.php.net/package/psi" rel="external"
+                                                       >PECL</a>,
+                                               <a href="https://mdref.m6w6.name/psi" rel="external"
+                                                       >Docs</a>
+                                       </td>
+                               </tr -->
+                               <tr>
+                                       <th>pecl/http</th>
+                                       <td>PHP HTTP Extension</td>
+                                       <td>
+                                               <a href="https://github.com/m6w6/ext-http" rel="external"
+                                                       >Github</a>,
+                                               <a href="https://git.m6w6.name/?p=m6w6/ext-http" rel="external"
+                                                       >Mirror</a>,
+                                               <a href="http://pecl.php.net/package/pecl_http" rel="external"
+                                                       >PECL</a>,
+                                               <a href="https://mdref.m6w6.name/http" rel="external"
+                                                       >Docs</a>
+                                       </td>
+                               </tr>
+                               <tr>
+                                       <th>pecl/pq</th>
+                                       <td>PHP PostgreSQL Extension</td>
+                                       <td>
+                                               <a href="https://github.com/m6w6/ext-pq" rel="external"
+                                                       >Github</a>,
+                                               <a href="https://git.m6w6.name/?p=m6w6/ext-pq" rel="external"
+                                                       >Mirror</a>,
+                                               <a href="http://pecl.php.net/package/pq" rel="external"
+                                                       >PECL</a>,
+                                               <a href="https://mdref.m6w6.name/pq" rel="external"
+                                                       >Docs</a>
+                                       </td>
+                               </tr>
+                               <tr>
+                                       <th>pharext</th>
+                                       <td>PHP Extension Installer</td>
+                                       <td>
+                                               <a href="https://github.com/pharext/pharext" rel="external"
+                                                       >Github</a>,
+                                               <a href="https://git.m6w6.name/?p=pharext/pharext" rel="external"
+                                                       >Mirror</a>,
+                                               <a href="https://pharext.org" rel="external"
+                                                       >Website</a>
+                                       </td>
+                               </tr>
+                       </table>
+               </section>
diff --git a/m6w6.jpg b/m6w6.jpg
new file mode 100644 (file)
index 0000000..e661ec9
Binary files /dev/null and b/m6w6.jpg differ
diff --git a/m6w6.png b/m6w6.png
new file mode 100644 (file)
index 0000000..1b55a1a
Binary files /dev/null and b/m6w6.png differ
diff --git a/openpgp.key b/openpgp.key
new file mode 100644 (file)
index 0000000..071f0d9
--- /dev/null
@@ -0,0 +1,106 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+mQENBFDcYVsBCADZmu3ac2q1H+Tz8S3XrNQGs+TBHRBpEsafPQBn6wpdMdJ/GDeS
+YxwoItoyjLWmg8cc45SWLYHzU3gkcSgljoivYnwbLbEZnCqE1V//oQYaMIAcQvO6
+nnGHWcFN6WyRl6wl3K866fYmwzE+H2JymjIY0YBdV7/oXDRUNrGaF7C7XAjY13sI
+0Uq8BV/q6J3e0xTQw+VAaf6X7mQvQjIgNipTe44ozVPEJSfNpUzPn2uV8ancWru6
+dmtm3fZZkGUcxNhXsVsEX7R1iHNWBuXSqsKmi5KViWbajg6juha/rbQd2b05PxJG
+H6ctGyMeU9ubJqIoVBpHeGyuGaizcv98686NABEBAAG0JU1pY2hhZWwgV2FsbG5l
+ciAobTZ3NikgPG1pa2VAcGhwLm5ldD6JATcEEwEIACEFAla0mo8CGwMFCwkIBwIG
+FQgJCgsCBBYCAwECHgECF4AACgkQSA4+FLCkx8dRVAf/a1POvRGQnpIjhB6AplnF
+Ux3GaIUlrTiUkZMyhftfk7Wgr3b+X4UitoVTaBm6Zsd8wPCwL2T5fD1B3QBq6N+G
+RscCzOq87Co6ZmrLApBTqv89MvF8sCGGuXhKpAClLbe9Un9GFunbrnJk21Q6AqJV
+eIFSYPQ/LmPaAJ3oFifdPyI8W8OFB5GnkH7JImvFr/vH90zm0rt5hSwdpuV5Pxxb
+cCZkAuVw/8OZ+ZupWBqwo9keLTzaGuzLNtruP62OXuwKuaryw80eWfZn5SxI41NV
+joSLfDeoBdFarFtQFJUyEEXpuA4LED/aYxKbvTIZxTn/zC2mrheKn5iLKmJQjVCz
+69HMO8w5ARAAAQEAAAAAAAAAAAAAAAD/2P/gABBKRklGAAEBAAABAAEAAP/bAEMA
+CAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicgIiwjHBwoNyks
+MDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIy
+MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAJkAdAMB
+IgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAAC
+AQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQz
+YnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpz
+dHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbH
+yMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEB
+AAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEG
+EkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6
+Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeY
+mZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery
+8/T19vf4+fr/2gAMAwEAAhEDEQA/AMhtKhfcUAVhzuXiqsmn+dFhx0PJragi8tRu
+fORRJCz/ACoOD1oA5ySB4YxsIBJwKdp1xe2V0GjU5YjoeDWhdWpDAFSCO4plsga4
+O3kDj8aAO2tfEd/5CKCqvtwSRn8qDrGobt32lifTAxWTaggfMvT1qzkYOaAOm0rx
+KJJBDe4Rzwsg6H6+ldEBk5B4NeZko3VhXQ6Jr3k7ba6fMfRZD29jQB1h96TODim7
+1cAqQQe4NOTuaAEIBPIppA52nmnkjnNKAPoaAK4I5zkEHFUtS0yHUogrlkdeUdT0
+NaZUHrzUR2qcjIycYNAHj3iGx8SrqZSTTxdFECiaNPvjJxn3or2AjJ6fnRQB5Ek5
+83yz1AzV5JABWXu/0uRh6AVJLdCKMkmgCzd3iQxnABY8DPrUNjFsUuwyTyapwRvc
+yCV+B2FbNvF8nTmgCcSrGm7tVGe7eViqYGOvoBUeoSC0gaQknn9ayraC9v3GYnSI
+nJJ4zQBcmu4Yl3Sz9OwqvFr0SzBIX3EdV9a0otFt42G9IxxyDyTVqKCzjbMcChh3
+xQBraTrFzAiyxMQhGfLccV1mm6zDekgsUlPPlt/Q964AzPvwBxV6At5atkh16GgD
+0XduOD1prDB4NYmi6wJ8W1wcTfwt/e/+vW7xkYoAb8xlGCNuOQRzmgx/MWJP07VI
+AOfWo1lBlMZPzAZ/CgBNoPUD8aKeRz2ooA8M84B5Wz1Y1DFm6m5+6OlZ73JFsr5+
+9z+daOnNhFIxzQBrRRHCgda1oEKr93OetUbVhnJ61qRuOKAKc0cLOHZAzL0z2pgl
+Zu2K0mijkOSoB9RUTWyg/LQBnne2G9O5qaMhnCBck9T6VWur9La5MbrwvSq76oGc
+CMbR14oA3jbRRD5xzjqaSGVXJVT0qhFdPcp8zEnHU1JbMlvK5Y8EUAXHYqQynDDk
+Edq7DRdTGoWnzn96nD/415/d6nbW4zLPGgP95sVZ0DXrSLU4miuo2VztYK45BoA9
+Kzg5UZpVIJJH601GBXcDSnn64oAUnmik3AcGigD5kluP3UCZ9K3NOnUgA81ysb75
+oh221q2Mvl3QRj9KAO1hfkFfyrRikz7dqw4ZdyAhuauRSOMfzoA3IwWAxT9rjvVC
+3uynJIxWFr3jm10tjFGPOn/uKeB9TQBu3+nQXQ3udrDvWLJaxw/KrA159qPjTWb9
+iBcGCM/wx8frWUuraiJA4vJiw/vOTQB69asUOM8VmeKr+ay08PCcSM20VieGvEpu
+bpLa9cK7cK3Yn+lbfiqD7Zaw+SwcxtkheaAPL5bme4lMk0jO56ljmrFpeyQOCGIx
+TpdMuFlcxwSPHnghT0oGn3JwPK2E/wB9gD+VAHq/g/x5cWqRJdu09rjDA8sn09R7
+V61b3MN5AtxbSrJG4BBU5r5o0y0vLV0IKspI+Ugj+de8eC9EbQ9HkeZ8yXT+a6rn
+amQOAKAOi/SilCDHIJ96KAPl5dNvIYVu5I9sQOAT71dwCUdfvCtCcz31sYFY4YdB
+0rGhlKkxOMMpwRQB0VpOdqk9q00m3YYHFYdjJuI54rXCb0+TPSgDM1/xIdMtjHCE
+eaUFACfucfex+PFedO7OxZmJJOSTWhrW+TUZ92c54zWaiknHU+lABUiKSa1tK8O3
+WoygbTGnc4yfyro4NEs9LkVZCZJR1C8kfj2/CgDE0nw9d3sy5Ro04O7v+VeuWWlS
+SWyLO+1AoG2MYz9TWXpzwrGEhj2g88CumhcpEN55xQBRPhywMbKEPzdRnrWPe+EI
+GOYWC10rS8kg1CZcHk0AcvB4XjtMu8hZu3pXqeh3aTaZAqHlFCkH2rkHkEgwATTt
+LvX0/UYDn92zhXHseM0Aehb17/zoqE8npRQB876Oz3mnxus7LtYAgdjVfVrGeHfc
+OnIP+sXow96l0awmsZZUSQPFIPlz1DCtW+aK801wzlGPDD3oA5/S79GkClsenvW/
+e6tHp2nNKCDKflRfUmvPPMksr1sH7jfnXR6akuoXEd3cjKIP3aH+dADZtOub+ITX
+axrKwyAqYIq3pug28JEjr5j+/FbiRCTG7tVuKFFP3aAGQFgPJTbFH6IMVq2ek2p+
+YkMe+etQRogPIq9DLGhG1ST7CgDSgghhXCIop0jYIxwPWoo2lk+7Hj3JxUiwD70r
+bj6DpQAqL5rZz8vr608xKOi/nS+YAOKjaXrQAjqAOWA9hVG5IZSq8Ejg+9Ts4z3/
+ABqvK2TQBbf4nWtkkUEtpLLKqAOwI+93ornG0OWeR5I7ZnVmJBCZ70UActb3LRyB
+8n5TWbrWqq7yLGSuefxq0TtkYH1rD1qFlk87Hyk4zQBmks8gYnP1rrNG1SFIVhkj
+ZSOh7VySN3zWnp0xMi56UAeg2zxyqGVsg1bBI4ArIsXUopXGO4q88gyPmIoA0YpZ
+F42g1ZWSRh90D8ayo5M/xmrMT88scUAa8Mki8GQAe1WGlGODWWki445qcSA8daAL
+AlLE0pJ4qv5qocmmNfIG25+lAFhyvXNVZG75qvdXqiPINUhfoULFh7c0Ad9oWjPq
+WlpcQXkkSliCqnjINFaPw+dP+EUiZnXJkc9feigDwm9t9q78Hjqax7xRNAyMcgjg
++hrpXAmhKAbWPUE/yrlroGKV0OeO9AGFyjFT2q1ZTeW+Qear3I/eEio43KkUAd1o
+98rpsYcg1qyzBSCe9cBaai8Dhh2robfWxPhXwaAOiSZCODU0c/bpWMs6/eBytTx3
+CNnDc0AbiXHuKl+1qFPzYrA+1qvVsVHPqaohAYHtQBqTX5YMEfNUV1Bmb5m+YDjN
+YbaiyZCncc5qpJekNvBOQ1AGzf6ocABjwKzHvppJoYoictwceuazp7sH77ZOcgCu
+l8F6cL7VPtk52JFyinuaAPSdKjl07TILZWcbF5we/eipcN2ciigDzs7CpyOaydVt
+d8e9Vyf7wrcDxyJtcbT69qiltXCZTDr14oA8/kGJgDUcsO07h93+VbWs2JSTzUTH
+cjFUUwy/WgCiH4wMUCVgcg4PtVmSzJBeIcdcVTOQeRQBpW2rzQcHke4q9FrSGQMV
+x61z+aUHFAG/NqrOoCdfWqol8z5pZOD2FZqyEUBmPAzQBelnCH5GBwaikut3C9KW
+30u9u3VYoHbccA44rtdI8CLF+8vvnfGVQfdB96AMTw54ffU7iOW4VvJZsKAOW/8A
+rV6M+mpGEDbUK8RzRjBHsRVK1aXTZl+QxlOF44A9q34LiHUIxjAl/u9moAyv7Vu7
+QmG4haR1/jVSQR60VekWSJysciBR2ccj2ooA89tNe066wPM8tz/DJx+tbEaB4w8M
+n5d64647fWup0L/kH/8AAjQBHfq+zEqZHriuUu4RDLlfuk1393/qT9K5q7/1f40A
+ZVspJFXG0yC5HzoAfUcVYh6irkXagDB/4Rxef3+B2+WprPwddXmSs0YUdyDzXR/w
+H6Vs6b/qhQBgWvw+hWINc3LtJ/dQYFdDp/hrSbaNAloGkX+N+STWmPuipIupoAiW
+2SN87QAOwGKnJGMqSKjk60qdBQASQrOhWRN3uOtZZhltpwsZOOoPTFbq1Xm/1ooA
+q7z35Pcn1oqZutFAH//ZiQE3BBMBCAAhBQJWtJr9AhsDBQsJCAcCBhUICQoLAgQW
+AgMBAh4BAheAAAoJEEgOPhSwpMfHlEMH/2RkL13XEBxSLUV+E+KqpWexYb3HQwR7
+Dss8EQ1fBoEuYCqfb7zG1CqYyDKkIobKvg1S47n0abvdffEcdLf8S96oqq1n/CmL
+uKvjvmyHeF0gBMWXIb+YlKixj7Mpc2mufDBonSM51n4W6pFXWpvQhanje6faZSa0
+cgzjTYlQy/E+OAA8STprI9WcLOIlaBHA2YUultojm4cBh222nMPnnSqevjoPwZTz
+LqwPgRj+VcUBGCoX/rqPfJqw7jtIIpXwxLOt4pLG84BoTes+qb/kRDIcU0Wbd9Cn
+LocZEi+Zj5L94YkaXRFNaKKjSwBvy5CmSQWgGN2vHPBjd8gmMwW2qf25AQ0EUNxh
+WwEIAMZln5hJQ7c+yMzjh01pd/7y4odXQEc4CUr+tr9ppEMHG/VMjJjOWQ8mGcN+
+mRaEsq3A8VIqVny5N8IlffnajonQR2lVSfTrm9eRWRNIuMJBzwqJZLxBgq8MVgUi
+0KLmHrfWM3lkfwszg8pVDzQzllqsjgE/tgOvLY20SEAzjSYa6iT2Pg1mYpxHsBPB
+cQBYHIwjxhuddr0z5m4Ozp1hlrNaDkUxXqwDFsjX8WHaYTFWnfG9Li193LFFxfl1
+QkHMBMMX5orgw2FC5qmHA7JG5xtZQwX6RJ4EWSG0OJpdeY4aHHOEr0JzyrTagV+p
+Nz1nf6nY5OSRvF/b2GQ6xtdQXsEAEQEAAYkBHwQYAQIACQUCUNxhWwIbDAAKCRBI
+Dj4UsKTHx7cGCAC4ubC2OxTtqIk4ochy3iV5Xlftrj+vSoKGXYXafDP8DgHOmxq9
+y9sBCpRdZXAiQGQaoJuqz1/BxVoIh/BSICRGkdnnDrfhTS6kdAyl05u/OXaYx8UB
+Thm1TNsyvgbA/V56brd+HfTXF4cjngAYYt3iCVAE1mNtdDsgvbIhBoqQSCtHi52x
+ZWlDrfNy++cp+0w+fC0pof0qdxhhaa5jS/uVq0spdbsu26PtaouJzlopBS99ZWoU
+OGbO90k/Rnk23fsCw6krxw/xj/WfGPIzcPp4gYSji7xRaz+xFE3Iao0d+sT6LH/z
+J6nRE0YmlfXPie+tl+788BWs0gmwGeYfAiC+
+=9TCv
+-----END PGP PUBLIC KEY BLOCK-----
\ No newline at end of file
diff --git a/robots.txt b/robots.txt
new file mode 100644 (file)
index 0000000..4738d6a
--- /dev/null
@@ -0,0 +1,3 @@
+User-agent: *
+Disallow:
+
diff --git a/x509.crt b/x509.crt
new file mode 100644 (file)
index 0000000..ffefd02
--- /dev/null
+++ b/x509.crt
@@ -0,0 +1,37 @@
+-----BEGIN CERTIFICATE-----
+MIIGajCCBVKgAwIBAgICY38wDQYJKoZIhvcNAQELBQAwgYwxCzAJBgNVBAYTAklM
+MRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQLEyJTZWN1cmUgRGlnaXRh
+bCBDZXJ0aWZpY2F0ZSBTaWduaW5nMTgwNgYDVQQDEy9TdGFydENvbSBDbGFzcyAy
+IFByaW1hcnkgSW50ZXJtZWRpYXRlIENsaWVudCBDQTAeFw0xNTA0MDMwMTQ2NTNa
+Fw0xNzA0MDIxNDI1MDdaMHUxCzAJBgNVBAYTAkFUMRMwEQYDVQQIEwpCdXJnZW5s
+YW5kMRAwDgYDVQQHEwdOZXVmZWxkMRgwFgYDVQQDEw9NaWNoYWVsIFdhbGxuZXIx
+JTAjBgkqhkiG9w0BCQEWFm1pa2UucGhwLm5ldEBnbWFpbC5jb20wggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCyy7CorF7hmBwe97+AutV+8rdMUZ9IEMP8
+n9r3olIomFugyrGj7Un4X5TTNSi6wHZc73Ijlhkbq4ftBBWMP00xfOV+2dpcjxwV
+1Xy/Y1C7QYUGGUpCV70aLc7fozSWDJl3/xK8flAEwYxZlkBdaYByKoewcNjFqDLL
+Wz/yMV4E+cJPcS6VvBiqvRtCvlQPEH6GSQRgwFo0+Ww5IKuQFwLNPPQjfkUDntJG
+BvJKiQJCSTWjhmmGcG4mOvU1d5o0jCdcWQL5W28eIpY9qO2CwUQLUHABoPGKQuh2
+lLPn5s9fbP8SAKcV4I8ldJLxdOlkFk+bYnAk9FDthZ4A6DQ2xx4lAgMBAAGjggLq
+MIIC5jAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHSUEFjAUBggrBgEFBQcD
+AgYIKwYBBQUHAwQwHQYDVR0OBBYEFNGG6lhSx7iAkr/zXFpDmEK8lXWkMB8GA1Ud
+IwQYMBaAFK5Vg2/sMcq59x36r2sx88gd46y7MC8GA1UdEQQoMCaBFm1pa2UucGhw
+Lm5ldEBnbWFpbC5jb22BDG1pa2VAcGhwLm5ldDCCAUwGA1UdIASCAUMwggE/MIIB
+OwYLKwYBBAGBtTcBAgMwggEqMC4GCCsGAQUFBwIBFiJodHRwOi8vd3d3LnN0YXJ0
+c3NsLmNvbS9wb2xpY3kucGRmMIH3BggrBgEFBQcCAjCB6jAnFiBTdGFydENvbSBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTADAgEBGoG+VGhpcyBjZXJ0aWZpY2F0ZSB3
+YXMgaXNzdWVkIGFjY29yZGluZyB0byB0aGUgQ2xhc3MgMiBWYWxpZGF0aW9uIHJl
+cXVpcmVtZW50cyBvZiB0aGUgU3RhcnRDb20gQ0EgcG9saWN5LCByZWxpYW5jZSBv
+bmx5IGZvciB0aGUgaW50ZW5kZWQgcHVycG9zZSBpbiBjb21wbGlhbmNlIG9mIHRo
+ZSByZWx5aW5nIHBhcnR5IG9ibGlnYXRpb25zLjA2BgNVHR8ELzAtMCugKaAnhiVo
+dHRwOi8vY3JsLnN0YXJ0c3NsLmNvbS9jcnR1Mi1jcmwuY3JsMIGOBggrBgEFBQcB
+AQSBgTB/MDkGCCsGAQUFBzABhi1odHRwOi8vb2NzcC5zdGFydHNzbC5jb20vc3Vi
+L2NsYXNzMi9jbGllbnQvY2EwQgYIKwYBBQUHMAKGNmh0dHA6Ly9haWEuc3RhcnRz
+c2wuY29tL2NlcnRzL3N1Yi5jbGFzczIuY2xpZW50LmNhLmNydDAjBgNVHRIEHDAa
+hhhodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS8wDQYJKoZIhvcNAQELBQADggEBAJB3
+kdZlLcR6LMPf+lQt6ITWKh5yZ/A+9lvJJGqnxpVBac/F78ohoHGg5K3HcGDtqEk9
+PvBJykyqg5/v8T/GansHYqyc7W7dAHtAvHV+GXhkgcBtQycldw9qXaJXPLQqzf2s
+Sgju0DZ+sHjI7HJCpGKEqo8rLqGR5rAZr6qWbRLLirksDNrV8Z8MadNdr1qyGciw
+t1fzV3RtozYdOLyCL+r0suOLZX5mAQfQM649e/q8Wym/G9qoHozsFl5PCvwMgJU1
+2WMh8ViRpwT/SipTs8McqgOb0VfTgHSDT3VxuLRzO2Sk7L673LkBGYhP6eZtaX0h
+hfM3+p28/joaf4a29Xk=
+-----END CERTIFICATE-----
diff --git a/x509.key b/x509.key
new file mode 100644 (file)
index 0000000..baec884
--- /dev/null
+++ b/x509.key
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAssuwqKxe4ZgcHve/gLrV
+fvK3TFGfSBDD/J/a96JSKJhboMqxo+1J+F+U0zUousB2XO9yI5YZG6uH7QQVjD9N
+MXzlftnaXI8cFdV8v2NQu0GFBhlKQle9Gi3O36M0lgyZd/8SvH5QBMGMWZZAXWmA
+ciqHsHDYxagyy1s/8jFeBPnCT3EulbwYqr0bQr5UDxB+hkkEYMBaNPlsOSCrkBcC
+zTz0I35FA57SRgbySokCQkk1o4ZphnBuJjr1NXeaNIwnXFkC+VtvHiKWPajtgsFE
+C1BwAaDxikLodpSz5+bPX2z/EgCnFeCPJXSS8XTpZBZPm2JwJPRQ7YWeAOg0Nsce
+JQIDAQAB
+-----END PUBLIC KEY-----