sotarokを勝手に祝う会
sotarokを勝手に祝う会に行ってまいりました!
僭越ながらこのたびはLTをさせていただいたので、その内容の紹介をさせていただきたく。(日立風)
皆様ご存知のことと思いますが、OSSコミュニティーにおいて、開発者が結婚する際には、新郎と新婦に
オリジナル○○○○○○○○○○○
を贈呈するという慣習があります。
はい、もちろん
オリジナルApacheモジュール
ですね。
というわけで、今回は
- mod_sotarok
- mod_mikko
を作らせていただきました。
mod_sotarok-mod_mikko at github.com
mod_sotarok.c:
/* * Copyright (c) 2010 Moriyoshi Koizumi * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "httpd.h" #include "http_config.h" #include "http_core.h" #include "http_log.h" #include "http_main.h" #include "http_protocol.h" #include "http_request.h" #include "util_script.h" #include "http_connection.h" #include "apr_strings.h" #include <stdio.h> module AP_MODULE_DECLARE_DATA sotarok_module; static const char *data[] = { "VAAAAAgAAAABAAEAAAADAAEAAQAAAAIAAQADAAAAAgABAAQAAAACAAEABAAAAAIAAQABAAAAAwABAAEAAAAH", "AAEAAQAAAAMAAQABAAAAAQABAAUAAAABAAEABAAAAAIAAQAEAAAAAwABAAMAAAACAAEAAQAAAAMAAQABAAAA", "AgABAAQAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAABAAEAAQAAAAMAAQABAAAAAQABAAEAAAADAAEAAQAA", "AAEAAQABAAAAAwABAAEAAAABAAEAAQAAAAMAAQABAAAABwABAAEAAAADAAEAAQAAAAEAAQABAAAABQABAAEA", "AAADAAEAAQAAAAEAAQABAAAAAwABAAEAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAABAAEAAQAAAAcAAQAB", "AAAAAwABAAEAAAADAAEAAQAAAAEAAQABAAAAAwABAAEAAAABAAEAAQAAAAMAAQABAAAAAQABAAEAAAADAAEA", "AQAAAAIAAQABAAAAAQABAAEAAAAIAAEAAQAAAAEAAQABAAAAAQABAAEAAAABAAEAAQAAAAUAAQABAAAAAwAB", "AAEAAAABAAEAAQAAAAMAAQABAAAAAwABAAEAAAADAAEAAgAAAAIAAQABAAAAAQABAAEAAAAHAAEAAQAAAAMA", "AQAFAAAAAQABAAUAAAABAAEABAAAAAIAAQAEAAAAAwABAAEAAAABAAEAAQAAAAgAAQABAAAAAQABAAEAAAAB", "AAEAAQAAAAEAAQAEAAAAAgABAAEAAAADAAEAAQAAAAEAAQABAAAAAwABAAEAAAADAAEAAQAAAAMAAQABAAAA", "AQABAAEAAAABAAEAAQAAAAEAAQABAAAAAQABAAMAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAABAAEAAQAA", "AAMAAQABAAAAAQABAAEAAAAFAAEAAQAAAAcAAQABAAAACQABAAEAAAABAAEAAQAAAAEAAQABAAAAAQABAAEA", "AAAFAAEAAQAAAAMAAQABAAAAAQABAAEAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAACAAEAAgAAAAEAAQAB", "AAAAAwABAAEAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAABAAEAAQAAAAMAAQABAAAAAQABAAEAAAAFAAEA", "AQAAAAcAAQABAAAACQABAAEAAAABAAEAAQAAAAEAAQABAAAAAQABAAEAAAAFAAEAAQAAAAMAAQABAAAAAQAB", "AAEAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAADAAEAAQAAAAEAAQABAAAAAwABAAEAAAAHAAEAAQAAAAMA", "AQABAAAAAQABAAEAAAADAAEAAQAAAAEAAQABAAAABQABAAEAAAAHAAEAAQAAAAoAAQABAAAAAQABAAEAAAAC", "AAEABQAAAAEAAQAEAAAAAgABAAQAAAADAAEAAwAAAAIAAQABAAAAAwABAAEAAAACAAEABAAAAAMAAQABAAAA", "AwAAAFQAAAAAAA==" }; static int sotarok_handler(request_rec *r) { int i; if (strcmp(r->handler, "sotarok-handler")) { return DECLINED; } ap_set_content_type(r, "text/plain; charset=US-ASCII"); if (r->header_only) return OK; for (i = 0; i < sizeof(data) / sizeof(data[0]); i++) { ap_rputs(data[i], r); ap_rputs("\n", r); } return OK; } static void sotarok_register_hooks(apr_pool_t *p) { ap_hook_handler(sotarok_handler, NULL, NULL, APR_HOOK_MIDDLE); } module AP_MODULE_DECLARE_DATA sotarok_module = { STANDARD20_MODULE_STUFF, NULL, /* per-directory config creator */ NULL, /* dir config merger */ NULL, /* server config creator */ NULL, /* server config merger */ NULL, /* command table */ sotarok_register_hooks /* set up other request processing hooks */ };
mod_mikko.c
/* * Copyright (c) 2010 Moriyoshi Koizumi * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include <assert.h> #include "httpd.h" #include "http_config.h" #include "http_core.h" #include "http_log.h" #include "http_main.h" #include "http_protocol.h" #include "http_request.h" #include "util_script.h" #include "http_connection.h" #include "apr_strings.h" #include <stdio.h> module AP_MODULE_DECLARE_DATA mikko_module; static unsigned int read_u32le(const char *p) { return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); } static unsigned int read_u16le(const char *p) { return p[0] | (p[1] << 8); } static char *base64_decode_all(apr_pool_t *pool, const char *buf, apr_size_t buf_len, apr_size_t *result_len) { const char *p, *e = buf + buf_len; char *result, *q; q = result = apr_palloc(pool, (buf_len / 3) * 4); p = buf; while (p < e) { int l = apr_base64_decode(q, p); if (l == 0) p++; else { assert(l > 0); q += l; p += ((l + 2) / 3) * 4; } } *result_len = q - result; return result; } static apr_status_t mikko_do_out_filter(ap_filter_t *f, apr_bucket_brigade *bb) { static const char prologue[] = "<html>\n\ <head>\n\ <title>Happy Wedding!</title>\n\ <style type=\"text/css\">\n\ .colored { color: red; }\n\ .uncolored { color: lightgray; }\n\ </style>\n\ </head>\n\ <body>\n\ <pre>"; static const char epilogue[] = "</pre>\n\ </body>\n\ </html>\n"; static const char span_colored_open[] = "<span class=\"colored\">"; static const char span_uncolored_open[] = "<span class=\"uncolored\">"; static const char span_close[] = "</span>"; apr_status_t err = APR_SUCCESS; char *buf = 0; apr_size_t buf_len = 0; char *decoded_data = 0; unsigned int width, height; const char *p, *pe; const char *q; err = apr_brigade_pflatten(bb, &buf, &buf_len, f->r->pool); if (err) return err; apr_brigade_cleanup(bb); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create( prologue, sizeof(prologue) - 1, f->c->bucket_alloc)); { apr_size_t decoded_len; p = decoded_data = base64_decode_all(f->r->pool, buf, buf_len, &decoded_len); pe = decoded_data + decoded_len; } if (p >= pe) goto error; width = read_u32le(p), p += 4; if (p >= pe) goto error; height = read_u32le(p), p += 4; q = buf; for (;;) { int v, c; if (p >= pe) goto error; v = read_u16le(p), p += 2; if (p >= pe) goto error; c = read_u16le(p), p += 2; if (!c) break; if (v) { APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create( span_colored_open, sizeof(span_colored_open) - 1, f->c->bucket_alloc)); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_transient_create(q, c, f->c->bucket_alloc)); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create( span_close, sizeof(span_close) - 1, f->c->bucket_alloc)); } else { APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create( span_uncolored_open, sizeof(span_uncolored_open) - 1, f->c->bucket_alloc)); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_transient_create(q, c, f->c->bucket_alloc)); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create( span_close, sizeof(span_close) - 1, f->c->bucket_alloc)); } q += c; while (*q == '\n') { APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_transient_create(q, 1, f->c->bucket_alloc)); q++; } } APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create( span_uncolored_open, sizeof(span_uncolored_open) - 1, f->c->bucket_alloc)); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_transient_create( q, buf_len - (q - buf), f->c->bucket_alloc)); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create( span_close, sizeof(span_close) - 1, f->c->bucket_alloc)); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create( epilogue, sizeof(epilogue) - 1, f->c->bucket_alloc)); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(f->c->bucket_alloc)); f->r->content_type = "text/html; charset=US-ASCII"; return ap_pass_brigade(f->next, bb); error: APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create( "error", sizeof("error") - 1, f->c->bucket_alloc)); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(f->c->bucket_alloc)); return ap_pass_brigade(f->next, bb); } static void mikko_register_hooks(apr_pool_t *p) { ap_register_output_filter("MIKKO_OUT", mikko_do_out_filter, NULL, AP_FTYPE_RESOURCE); } module AP_MODULE_DECLARE_DATA mikko_module = { STANDARD20_MODULE_STUFF, NULL, /* per-directory config creator */ NULL, /* dir config merger */ NULL, /* server config creator */ NULL, /* server config merger */ NULL, /* command table */ mikko_register_hooks /* set up other request processing hooks */ };
mod_sotarokを次のように組み込んで
LoadModule sotarok_module .libs/mod_sotarok.so Listen 8080 <Location /> SetHandler sotarok-handler </Location> PidFile /tmp/httpd.pid LockFile /tmp/accept.lock ErrorLog /tmp/error_log
Apacheにリクエストを投げると、次のような文字列が帰ってきます。
VAAAAAgAAAABAAEAAAADAAEAAQAAAAIAAQADAAAAAgABAAQAAAACAAEABAAAAAIAAQABAAAAAwABAAEAAAAH AAEAAQAAAAMAAQABAAAAAQABAAUAAAABAAEABAAAAAIAAQAEAAAAAwABAAMAAAACAAEAAQAAAAMAAQABAAAA AgABAAQAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAABAAEAAQAAAAMAAQABAAAAAQABAAEAAAADAAEAAQAA AAEAAQABAAAAAwABAAEAAAABAAEAAQAAAAMAAQABAAAABwABAAEAAAADAAEAAQAAAAEAAQABAAAABQABAAEA AAADAAEAAQAAAAEAAQABAAAAAwABAAEAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAABAAEAAQAAAAcAAQAB AAAAAwABAAEAAAADAAEAAQAAAAEAAQABAAAAAwABAAEAAAABAAEAAQAAAAMAAQABAAAAAQABAAEAAAADAAEA AQAAAAIAAQABAAAAAQABAAEAAAAIAAEAAQAAAAEAAQABAAAAAQABAAEAAAABAAEAAQAAAAUAAQABAAAAAwAB AAEAAAABAAEAAQAAAAMAAQABAAAAAwABAAEAAAADAAEAAgAAAAIAAQABAAAAAQABAAEAAAAHAAEAAQAAAAMA AQAFAAAAAQABAAUAAAABAAEABAAAAAIAAQAEAAAAAwABAAEAAAABAAEAAQAAAAgAAQABAAAAAQABAAEAAAAB AAEAAQAAAAEAAQAEAAAAAgABAAEAAAADAAEAAQAAAAEAAQABAAAAAwABAAEAAAADAAEAAQAAAAMAAQABAAAA AQABAAEAAAABAAEAAQAAAAEAAQABAAAAAQABAAMAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAABAAEAAQAA AAMAAQABAAAAAQABAAEAAAAFAAEAAQAAAAcAAQABAAAACQABAAEAAAABAAEAAQAAAAEAAQABAAAAAQABAAEA AAAFAAEAAQAAAAMAAQABAAAAAQABAAEAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAACAAEAAgAAAAEAAQAB AAAAAwABAAEAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAABAAEAAQAAAAMAAQABAAAAAQABAAEAAAAFAAEA AQAAAAcAAQABAAAACQABAAEAAAABAAEAAQAAAAEAAQABAAAAAQABAAEAAAAFAAEAAQAAAAMAAQABAAAAAQAB AAEAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAADAAEAAQAAAAEAAQABAAAAAwABAAEAAAAHAAEAAQAAAAMA AQABAAAAAQABAAEAAAADAAEAAQAAAAEAAQABAAAABQABAAEAAAAHAAEAAQAAAAoAAQABAAAAAQABAAEAAAAC AAEABQAAAAEAAQAEAAAAAgABAAQAAAADAAEAAwAAAAIAAQABAAAAAwABAAEAAAACAAEABAAAAAMAAQABAAAA AwAAAFQAAAAAAA==
見たところ base64 なわけですが、これをデコードしてみると、
$ php -r 'echo bin2hex(base64_decode(file_get_contents("/tmp/out.txt")));' 540000000800000001000100000003000100010000000200010003000000020001000400000002000100040000000200010001000000030001000100000007000100010000000300010001000000010001000500000001000100040000000200010004000000030001000300000002000100010000000300010001000000020001000400000003000100010000000300010001000000030001000100000001000100010000000300010001000000010001000100000003000100010000000100010001000000030001000100000001000100010000000300010001000000070001000100000003000100010000000100010001000000050001000100000003000100010000000100010001000000030001000100000003000100010000000300010001000000030001000100000001000100010000000700010001000000030001000100000003000100010000000100010001000000030001000100000001000100010000000300010001000000010001000100000003000100010000000200010001000000010001000100000008000100010000000100010001000000010001000100000001000100010000000500010001000000030001000100000001000100010000000300010001000000030001000100000003000100020000000200010001000000010001000100000007000100010000000300010005000000010001000500000001000100040000000200010004000000030001000100000001000100010000000800010001000000010001000100000001000100010000000100010004000000020001000100000003000100010000000100010001000000030001000100000003000100010000000300010001000000010001000100000001000100010000000100010001000000010001000300000003000100010000000300010001000000030001000100000001000100010000000300010001000000010001000100000005000100010000000700010001000000090001000100000001000100010000000100010001000000010001000100000005000100010000000300010001000000010001000100000003000100010000000300010001000000030001000100000002000100020000000100010001000000030001000100000003000100010000000300010001000000030001000100000001000100010000000300010001000000010001000100000005000100010000000700010001000000090001000100000001000100010000000100010001000000010001000100000005000100010000000300010001000000010001000100000003000100010000000300010001000000030001000100000003000100010000000100010001000000030001000100000007000100010000000300010001000000010001000100000003000100010000000100010001000000050001000100000007000100010000000a0001000100000001000100010000000200010005000000010001000400000002000100040000000300010003000000020001000100000003000100010000000200010004000000030001000100000003000000540000000000
のように、何か意味ありげなオクテット列が続いていることが分かります。
では、mod_mikko.so を組み込んでみましょう。
LoadModule sotarok_module .libs/mod_sotarok.so LoadModule mikko_module .libs/mod_mikko.so Listen 8080 <Location /> SetHandler sotarok-handler SetOutputFilter MIKKO_OUT </Location> PidFile /tmp/httpd.pid LockFile /tmp/accept.lock ErrorLog /tmp/error_log
出力:
VAAAAAgAAAABAAEAAAADAAEAAQAAAAIAAQADAAAAAgABAAQAAAACAAEABAAAAAIAAQABAAAAAwABAAEAAAAH
AAEAAQAAAAMAAQABAAAAAQABAAUAAAABAAEABAAAAAIAAQAEAAAAAwABAAMAAAACAAEAAQAAAAMAAQABAAAA
AgABAAQAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAABAAEAAQAAAAMAAQABAAAAAQABAAEAAAADAAEAAQAA
AAEAAQABAAAAAwABAAEAAAABAAEAAQAAAAMAAQABAAAABwABAAEAAAADAAEAAQAAAAEAAQABAAAABQABAAEA
AAADAAEAAQAAAAEAAQABAAAAAwABAAEAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAABAAEAAQAAAAcAAQAB
AAAAAwABAAEAAAADAAEAAQAAAAEAAQABAAAAAwABAAEAAAABAAEAAQAAAAMAAQABAAAAAQABAAEAAAADAAEA
AQAAAAIAAQABAAAAAQABAAEAAAAIAAEAAQAAAAEAAQABAAAAAQABAAEAAAABAAEAAQAAAAUAAQABAAAAAwAB
AAEAAAABAAEAAQAAAAMAAQABAAAAAwABAAEAAAADAAEAAgAAAAIAAQABAAAAAQABAAEAAAAHAAEAAQAAAAMA
AQAFAAAAAQABAAUAAAABAAEABAAAAAIAAQAEAAAAAwABAAEAAAABAAEAAQAAAAgAAQABAAAAAQABAAEAAAAB
AAEAAQAAAAEAAQAEAAAAAgABAAEAAAADAAEAAQAAAAEAAQABAAAAAwABAAEAAAADAAEAAQAAAAMAAQABAAAA
AQABAAEAAAABAAEAAQAAAAEAAQABAAAAAQABAAMAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAABAAEAAQAA
AAMAAQABAAAAAQABAAEAAAAFAAEAAQAAAAcAAQABAAAACQABAAEAAAABAAEAAQAAAAEAAQABAAAAAQABAAEA
AAAFAAEAAQAAAAMAAQABAAAAAQABAAEAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAACAAEAAgAAAAEAAQAB
AAAAAwABAAEAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAABAAEAAQAAAAMAAQABAAAAAQABAAEAAAAFAAEA
AQAAAAcAAQABAAAACQABAAEAAAABAAEAAQAAAAEAAQABAAAAAQABAAEAAAAFAAEAAQAAAAMAAQABAAAAAQAB
AAEAAAADAAEAAQAAAAMAAQABAAAAAwABAAEAAAADAAEAAQAAAAEAAQABAAAAAwABAAEAAAAHAAEAAQAAAAMA
AQABAAAAAQABAAEAAAADAAEAAQAAAAEAAQABAAAABQABAAEAAAAHAAEAAQAAAAoAAQABAAAAAQABAAEAAAAC
AAEABQAAAAEAAQAEAAAAAgABAAQAAAADAAEAAwAAAAIAAQABAAAAAwABAAEAAAACAAEABAAAAAMAAQABAAAA
AwAAAFQAAAAAAA==
というわけで、
sotarok & komikko、おめでとうございます!末永くお幸せに!