From: Michael Wallner Date: Thu, 20 Jan 2022 19:48:47 +0000 (+0100) Subject: initial commit X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fm6w6.github.io;a=commitdiff_plain;h=1c57f0d966e3e2efa7bef55d94036a3614ca3527 initial commit --- 1c57f0d966e3e2efa7bef55d94036a3614ca3527 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62000dd --- /dev/null +++ b/.gitignore @@ -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 index 0000000..c2b8183 --- /dev/null +++ b/404.html @@ -0,0 +1,35 @@ +--- +permalink: /404.html +layout: default +styles: assets/index.css +--- + + + +
+

404

+ +

Page not found :(

+

The requested page could not be found.

+
diff --git a/Gemfile b/Gemfile new file mode 100644 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 index 0000000..299337e --- /dev/null +++ b/Gemfile.lock @@ -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 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 index 0000000..36fbf51 --- /dev/null +++ b/_config.yml @@ -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. +
+ 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 index 0000000..f181a4e --- /dev/null +++ b/_includes/ccsa.html @@ -0,0 +1,11 @@ +

+ + This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. + +
+ Creative Commons Share Alike License + +

diff --git a/_includes/foot.html b/_includes/foot.html new file mode 100644 index 0000000..5f85cab --- /dev/null +++ b/_includes/foot.html @@ -0,0 +1 @@ + diff --git a/_includes/head.html b/_includes/head.html new file mode 100644 index 0000000..04d6936 --- /dev/null +++ b/_includes/head.html @@ -0,0 +1,19 @@ + + + + + {{ page.title }} — {{ site.title }} + + + + {% feed_meta %} + +{% for style in page.styles %} + +{% endfor %} + +{% for script in page.scripts %} + +{% endfor %} + + diff --git a/_includes/pubinfo.html b/_includes/pubinfo.html new file mode 100644 index 0000000..7bdc4f0 --- /dev/null +++ b/_includes/pubinfo.html @@ -0,0 +1,12 @@ +
+

+ Posted by {{ page.author }} + on {{ page.date | date_to_long_string: "ordinal" }} + in {{ site.blog }}: + {% assign last_tag = page.tags | last %} + {% for tag in page.tags %} + {{ tag }}{% if tag != last_tag %}, {% endif %} + {% endfor %} +

+
diff --git a/_layouts/default.html b/_layouts/default.html new file mode 100644 index 0000000..a443452 --- /dev/null +++ b/_layouts/default.html @@ -0,0 +1,7 @@ +{% include head.html %} + +
+ {{ content }} +
+ +{% include foot.html %} diff --git a/_layouts/post.html b/_layouts/post.html new file mode 100644 index 0000000..1c69c0b --- /dev/null +++ b/_layouts/post.html @@ -0,0 +1,28 @@ +{% include head.html %} + + + +
+
+

{{ page.title }}

+ +
+
+
+ {% include pubinfo.html %} + {{ content }} +
+
+
+ + + + + +{% include foot.html %} diff --git a/_layouts/tags.html b/_layouts/tags.html new file mode 100644 index 0000000..48538ee --- /dev/null +++ b/_layouts/tags.html @@ -0,0 +1,37 @@ +--- +layout: default +styles: assets/index.css +--- +
+

{{ page.title }}

+ +
+
+

#{{ page.tag }}

+ +

See also

+

+ 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 %} + {{ tag }}{% if tag != last_tag %}, {% endif %} + {% endif %} + {% endfor %} +

+
diff --git a/_plugins/tags.rb b/_plugins/tags.rb new file mode 100644 index 0000000..9466f6c --- /dev/null +++ b/_plugins/tags.rb @@ -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 index 0000000..2dfdf52 --- /dev/null +++ b/_posts/2004-08-02-javascript-flexy.md @@ -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 `n"; + var $scriptData = "var foo = 'bar';"; +} +``` + +Outputting above object with the following template wont work: + +```html + + + +``` + +Instead: + +```html + +{scriptOpen:h} + {scriptData:h} +{scriptClose:h} + +``` + +...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 index 0000000..9e3ee18 --- /dev/null +++ b/_posts/2004-08-02-scrollable-overflowauto-elements-in-mozilla.md @@ -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 index 0000000..682bfdc --- /dev/null +++ b/_posts/2004-08-03-class-inheritance-or-containers.md @@ -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 index 0000000..d75a4b4 --- /dev/null +++ b/_posts/2004-08-04-dropping-server-load-with-http-caching.md @@ -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 index 0000000..292891d --- /dev/null +++ b/_posts/2004-08-05-update-overflowauto-in-mozilla.md @@ -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 index 0000000..92d2652 --- /dev/null +++ b/_posts/2004-08-25-extapr-exercise-or-joke.md @@ -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 index 0000000..afe8257 --- /dev/null +++ b/_posts/2004-09-12-hordechora-major-vulnaribility.md @@ -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 ~~... ~~ 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 index 0000000..3326172 --- /dev/null +++ b/_posts/2004-09-13-chora-already-fixed.md @@ -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 index 0000000..afc47fd --- /dev/null +++ b/_posts/2004-10-06-extvpopmail-no-thanks.md @@ -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: +```c +#include +#include +#include +#include +#include +#include +#include + +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", "a + ); + + 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 index 0000000..6ed30b0 --- /dev/null +++ b/_posts/2004-10-08-pearauth-and-vpop-xmlrpc.md @@ -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 index 0000000..1d2d48e --- /dev/null +++ b/_posts/2005-01-27-peclhttp.md @@ -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 index 0000000..0d01aef --- /dev/null +++ b/_posts/2005-03-04-peclhttp-060.md @@ -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 index 0000000..21492ed --- /dev/null +++ b/_posts/2005-06-05-moddomaintree.md @@ -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 index 0000000..b0c8523 --- /dev/null +++ b/_posts/2005-06-07-httprequestpool-in-peclhttp.md @@ -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 index 0000000..c1a4e29 --- /dev/null +++ b/_posts/2005-06-29-is-php-staying-language-i-want-to-work-with.md @@ -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 index 0000000..dcae7a7 --- /dev/null +++ b/_posts/2005-08-26-pecl-http-lap-12.md @@ -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 index 0000000..b8ea458 --- /dev/null +++ b/_posts/2005-09-12-tutorial-kinda-for-peclhttp.md @@ -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 "304 Not Modified" 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 index 0000000..08b5135 --- /dev/null +++ b/_posts/2005-10-04-references-in-php.md @@ -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 index 0000000..3bf75fc --- /dev/null +++ b/_posts/2005-11-13-obviously.md @@ -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 index 0000000..1f7b917 --- /dev/null +++ b/_posts/2005-11-13-php-51-around-the-corner.md @@ -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 index 0000000..b3f359e --- /dev/null +++ b/_posts/2005-11-16-submitting-bug-for-php.md @@ -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 index 0000000..119ec59 --- /dev/null +++ b/_posts/2005-11-16-submitting-patch-for-php.md @@ -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 index 0000000..02502ea --- /dev/null +++ b/_posts/2005-11-16-time-to-say-good-bye.md @@ -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 index 0000000..5e2475c --- /dev/null +++ b/_posts/2005-11-17-boost-your-website-with-apc.md @@ -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 `` +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 index 0000000..3147fc2 --- /dev/null +++ b/_posts/2005-12-06-hash-extension.md @@ -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 index 0000000..b6ac632 --- /dev/null +++ b/_posts/2005-12-06-peclhttp-nasty-bug-and-new-example.md @@ -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 index 0000000..fca969b --- /dev/null +++ b/_posts/2005-12-15-peclhttp-0200-outta-door.md @@ -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 index 0000000..fdb91cb --- /dev/null +++ b/_posts/2005-12-30-sfluentdecorated.md @@ -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 index 0000000..57b6c4d --- /dev/null +++ b/_posts/2006-01-27-apache2-moddomaintree-version-13.md @@ -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 index 0000000..c25a175 --- /dev/null +++ b/_posts/2006-01-27-imapsavebody.md @@ -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 index 0000000..71d3e09 --- /dev/null +++ b/_posts/2006-02-03-some-cool-new-features-of-peclhttp.md @@ -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 index 0000000..b28cb23 --- /dev/null +++ b/_posts/2006-02-15-peclhttp-update.md @@ -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 index 0000000..57c27d3 --- /dev/null +++ b/_posts/2006-03-07-end-of-youth.md @@ -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 index 0000000..6dfb21d --- /dev/null +++ b/_posts/2006-05-22-cookie-handling.md @@ -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 index 0000000..b40d855 --- /dev/null +++ b/_posts/2006-05-31-konquerors-viewmode-buttons.md @@ -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 + +``` + +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 index 0000000..596c46b --- /dev/null +++ b/_posts/2006-06-09-finally.md @@ -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 index 0000000..0d2a12a --- /dev/null +++ b/_posts/2006-06-11-installing-peclhttp.md @@ -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 index 0000000..1901bf9 --- /dev/null +++ b/_posts/2006-08-18-round-up.md @@ -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 index 0000000..cd43046 --- /dev/null +++ b/_posts/2006-08-21-get-and-array-rumors.md @@ -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 index 0000000..809ebf9 --- /dev/null +++ b/_posts/2006-09-16-httprequestdatashare.md @@ -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 [ class HttpRequestDataShare implements Countable ] { + + - Constants [0] { + } + + - Static properties [1] { + Property [ private static $instance ] + } + + - Static methods [1] { + Method [ static public method singleton ] { + + - Parameters [1] { + Parameter #0 [ $global ] + } + } + } + + - Properties [4] { + Property [ public $cookie ] + Property [ public $dns ] + Property [ public $ssl ] + Property [ public $connect ] + } + + - Methods [5] { + Method [ public method __destruct ] { + + - Parameters [0] { + } + } + + Method [ public method count ] { + + - Parameters [0] { + } + } + + Method [ public method attach ] { + + - Parameters [1] { + Parameter #0 [ HttpRequest $request ] + } + } + + Method [ public method detach ] { + + - Parameters [1] { + Parameter #0 [ HttpRequest $request ] + } + } + + Method [ 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 index 0000000..34085cd --- /dev/null +++ b/_posts/2007-02-08-http-curl-and-stuff.md @@ -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 index 0000000..6740a28 --- /dev/null +++ b/_posts/2007-02-10-something-i-didn-even-know-i-was-missing.md @@ -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 index 0000000..24c6f76 --- /dev/null +++ b/_posts/2007-04-01-upgrading-to-52.md @@ -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 index 0000000..63cb36f --- /dev/null +++ b/_posts/2007-05-03-apache-multiviews-are-evil.md @@ -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 index 0000000..77cae90 --- /dev/null +++ b/_posts/2007-05-03-two-pitfalls-in-one-afternoon.md @@ -0,0 +1,18 @@ +--- +title: Two pitfalls in one afternoon +author: m6w6 +tags: +- WTF +- WEB +--- + +This is not my day. + +<quote url=""> + +> words that are present in more than 50% of the rows are considered common and do not match + +</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 index 0000000..5d8cb46 --- /dev/null +++ b/_posts/2007-05-09-phar-vs-world.md @@ -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 index 0000000..b71aa31 --- /dev/null +++ b/_posts/2007-05-23-silence.md @@ -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 index 0000000..d0d414d --- /dev/null +++ b/_posts/2007-09-11-introducing-libcurls-multi-socket-api.md @@ -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 index 0000000..2897cd7 --- /dev/null +++ b/_posts/2008-11-18-qmail-spamassassin-selectivity.md @@ -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 index 0000000..81e2e08 --- /dev/null +++ b/_posts/2008-11-18-vpopmail-and-people-reaching-their-maildir-quota.md @@ -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 +#include +#include +#include + +#include +#include + +#include +#include + +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 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 index 0000000..641f70a --- /dev/null +++ b/_posts/2008-12-05-peclhttp-and-sub-second-timeouts.md @@ -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: + +<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. + +</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 index 0000000..701faac --- /dev/null +++ b/_posts/2009-04-10-php-commandline-highlighter.md @@ -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"), ""); + } 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/" => "", + "/
/" => "\n", + "/<\/span>/" => "", + "/( ){4}/" => "\t", + "/ /" => " ", + // convert colors + "//" => $this->color("comment"), + "//" => $this->color("default"), + "//" => $this->color("html"), + "//" => $this->color("keyword"), + "//" => $this->color("string"), + // fix colors before newline + #"/((\033\[\d+m)+)([[:punct:][:space:]]*)(\r?\n)/s" => "\$1\$3\$4\$1", + // start/stop + "//" => $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 index 0000000..478ec9c --- /dev/null +++ b/_posts/2009-04-20-looking-for-php-geeks-in-austria.md @@ -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: + + +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 index 0000000..55ef8ff --- /dev/null +++ b/_posts/2010-05-10-websockets-handshake-non-http-conforming.md @@ -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 index 0000000..c5d2e76 --- /dev/null +++ b/_posts/2011-03-14-courier-imap-authdaemond-and-vpopmails-vchkpw.md @@ -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 +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + +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 index 0000000..efecf93 --- /dev/null +++ b/_posts/2011-03-18-javascript-delaying.md @@ -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 index 0000000..91defff --- /dev/null +++ b/_posts/2013-02-19-peclhttp-v2-http2-or-httpi-or-http.md @@ -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 index 0000000..dc087e7 --- /dev/null +++ b/_posts/2013-03-03-peclhttp-175.md @@ -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 index 0000000..c566e59 --- /dev/null +++ b/_posts/2013-06-18-hear-hear.md @@ -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: + + + +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 index 0000000..e7eeaab --- /dev/null +++ b/_posts/2013-12-09-evolution-of.md @@ -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 index 0000000..d2c99a2 --- /dev/null +++ b/_posts/2015-08-11-testing-php-extensions-on-travis-ci.md @@ -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 index 0000000..0f3dd24 --- /dev/null +++ b/_posts/2015-08-19-blank-dell-on-displayport.md @@ -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 index 0000000..92f6e3c --- /dev/null +++ b/_posts/2016-04-16-debian-disabling-sslv3-in-courier-server.md @@ -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 +#include +#include + +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 <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 index 0000000..08ee66c --- /dev/null +++ b/_sass/post.scss @@ -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 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 index 0000000..7fe96e5 --- /dev/null +++ b/assets/index.scss @@ -0,0 +1,4 @@ +--- +--- + +@import "index"; diff --git a/assets/lapalma-c.jpg b/assets/lapalma-c.jpg new file mode 100644 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 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 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 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 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 index 0000000..fb042b4 --- /dev/null +++ b/assets/post.scss @@ -0,0 +1,4 @@ +--- +--- + +@import "post"; diff --git a/assets/rouge.css b/assets/rouge.css new file mode 100644 index 0000000..52970bf --- /dev/null +++ b/assets/rouge.css @@ -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 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 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 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 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 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 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 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 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 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 %} + +
+
+

{{ page.title }}

+ +
+
+ {% assign y_posts = site.posts | group_by_exp: "post", "post.date | slice: 0, 4" %} + {% for y in y_posts %} +

{{ y.name }}

+ {% 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" %} +

{{ month }}

+ {% 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" %} +

{{ day }}

+
    + {% for post in d.items %} +
  • + {{ post.title }} in + {% assign last_tag = post.tags | last %} + {% for tag in post.tags %} + {{ tag }}{% if tag != last_tag %}, {% endif %} + {% endfor %} +
  • + {% endfor %} +
+ {% endfor %} + {% endfor %} + {% endfor %} +
+
+ {% include ccsa.html %} +
+
+ +{% include foot.html %} diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..1b55a1a Binary files /dev/null and b/favicon.ico differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..3d74384 --- /dev/null +++ b/index.html @@ -0,0 +1,200 @@ +--- +title: Michael Wallner (m6w6) +layout: default +styles: assets/index.css +--- +
+
+ +
+

+ {{ site.title }} <> +

+

+ {{ site.description }} +

+
+
+

Identity

+

PGP, GPG

+

1EC3 C71D DD63 5831 A337 D684 480E 3E14 B0A4 C7C7

+ +
+
+

Contact

+ +
+
+

Social

+ +

Blog — Mike's sudden Inspirations

+
    + {% assign m6w6_posts = site.posts | where: "author", "m6w6" | slice: 0, 3 %} + {% for post in m6w6_posts %} +
  • {{ post.title }} + — posted {{ post.date | date_to_long_string: "ordinal" }}
  • + {% endfor %} +
+
+
+

Career

+ + + {% assign Y = "now" | date: "%Y" %} + {% assign rowspan = Y | minus: 2013 | plus: 1 %} + + + + + + + {% assign last_Y = Y | minus: 1 %} + {% for y in (2014..last_Y) reversed %} + + {% endfor %} + + + + + + + + + + + + + + + + + + + + + + + + +
{{ Y }}SmugMug Inc.SorcererRemote
{{ y }}
2013
INQNETSoftware DeveloperVienna
2012
2011
2010
2009
2008
2007
IWORKSFreelancerRemote
2006
2005
2004
2003
2002
+
+
+

Open source

+ + + + + + + + + + + + + + + + + + + + + + +
libmemcachedC/C++ library for memcached(1) (resurrected) + Github, + Mirror, + Docs, + Artifacts +
pecl/httpPHP HTTP Extension + Github, + Mirror, + PECL, + Docs +
pecl/pqPHP PostgreSQL Extension + Github, + Mirror, + PECL, + Docs +
pharextPHP Extension Installer + Github, + Mirror, + Website +
+
diff --git a/m6w6.jpg b/m6w6.jpg new file mode 100644 index 0000000..e661ec9 Binary files /dev/null and b/m6w6.jpg differ diff --git a/m6w6.png b/m6w6.png new file mode 100644 index 0000000..1b55a1a Binary files /dev/null and b/m6w6.png differ diff --git a/openpgp.key b/openpgp.key new file mode 100644 index 0000000..071f0d9 --- /dev/null +++ b/openpgp.key @@ -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 index 0000000..4738d6a --- /dev/null +++ b/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Disallow: + diff --git a/x509.crt b/x509.crt new file mode 100644 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 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-----